From 31980b06d50d530feb2c0f1db9daf24bd3b8797a Mon Sep 17 00:00:00 2001
From: Riku <risaku@163.com>
Date: 星期日, 15 六月 2025 22:50:16 +0800
Subject: [PATCH] 2025.6.15

---
 src/views/management/TaskSummary.vue |  401 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 380 insertions(+), 21 deletions(-)

diff --git a/src/views/management/TaskSummary.vue b/src/views/management/TaskSummary.vue
index 4bc0909..910d206 100644
--- a/src/views/management/TaskSummary.vue
+++ b/src/views/management/TaskSummary.vue
@@ -1,26 +1,385 @@
 <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="瀛e害姹囨��"></TaskSummaryItem>
-    </el-col>
-    <el-col :span="12">
-      <TaskSummaryItem title="骞村害姹囨��"></TaskSummaryItem>
-    </el-col>
-  </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>
 </template>
 
-<script setup></script>
+<script setup>
+import * as echarts from 'echarts'
+import { ref, onMounted } from 'vue'
+import dayjs from 'dayjs'
+import taskApi from '@/api/fysp/taskApi.js'
 
-<style scoped></style>
+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')
+  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(-7, 'day').format('YYYY-MM-DD HH:mm:ss')
+  area.endtime = dayjs(area.endtime).add(-7, '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: {},
+    numByScene: {},
+    numByUser: {}
+  }
+  // 闂鏁�
+  const proCount = {
+    numByTotal: {},
+    numByDistrict: {},
+    numByScene: {},
+    numByUser: {}
+  }
+  // 鏁存敼鏁�
+  const changeCount = {
+    numByTotal: {},
+    numByDistrict: {},
+    numByScene: {},
+    numByUser: {}
+  }
+  // // 鎸夌敤鎴峰垎绫�
+  // const userCount = {
+  //   numByTotal: {},
+  //   numByDistrict: {},
+  //   numByScene: {},
+  //   numByUser: {}
+  // }
+  dataList.forEach((d) => {
+    const tName = '鎬昏'
+    const dName = d.subtask.districtname
+    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.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.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.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
+  })
+
+  let series = {}
+  totalCount
+  proCount
+  changeCount
+  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: [0, 10],
+        },
+        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-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);
+}
+
+.bar-chart {
+  width: 400px;
+  height: 600px;
+}
+</style>

--
Gitblit v1.9.3