From f19e5267cc23b1c714dc746239864f33ed715dd9 Mon Sep 17 00:00:00 2001
From: riku <risaku@163.com>
Date: 星期五, 05 十二月 2025 17:55:02 +0800
Subject: [PATCH] 完成地图制作任务功能初版
---
src/views/fysp/task/components/CompMonitorPlan.vue | 304 ++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 233 insertions(+), 71 deletions(-)
diff --git a/src/views/fysp/task/components/CompMonitorPlan.vue b/src/views/fysp/task/components/CompMonitorPlan.vue
index 5b86666..acea676 100644
--- a/src/views/fysp/task/components/CompMonitorPlan.vue
+++ b/src/views/fysp/task/components/CompMonitorPlan.vue
@@ -1,44 +1,160 @@
<template>
<el-calendar
- v-loading="dayTaskLoading"
v-model="dateValue"
:range="dateRange"
@update:model-value="onDateChange"
>
<template #header="{ date }">
- <span>{{ title }}</span>
- <el-space>
- <el-tag>鎬昏锛歿{ taskStatistic.total }}</el-tag>
- <el-tag>瀹屾垚锛歿{ taskStatistic.complete }}</el-tag>
- <el-tag>鏁存敼锛歿{ taskStatistic.changed }}</el-tag>
- </el-space>
- <!-- <span>{{ date }}</span> -->
+ <div style="width: 100%">
+ <el-row justify="space-between">
+ <el-space>
+ <el-tag type="default"
+ >宸℃煡閲忥細{{
+ `${taskStatistic.complete}/${taskStatistic.total}`
+ }}</el-tag
+ >
+ <el-tag type="default"
+ >缁煎悎鏁存敼鐜囷細{{
+ formatPercent(
+ taskStatistic.changedProblemNum /
+ taskStatistic.totalProblemNum
+ )
+ }}</el-tag
+ >
+ <!-- <el-tag type="default">鏁存敼锛歿{ taskStatistic.changed }}</el-tag> -->
+ </el-space>
+ <el-space>
+ <el-text>鑱氱劍鐢ㄦ埛锛�</el-text>
+ <el-select
+ v-model="selectedUsers"
+ multiple
+ clearable
+ collapse-tags
+ :max-collapse-tags="1"
+ style="width: 150px"
+ >
+ <el-option
+ v-for="user in taskStatistic.progressPerUser"
+ :key="user.userId"
+ :label="user.userName"
+ :value="user.userName"
+ />
+ </el-select>
+ </el-space>
+ </el-row>
+ <el-row class="m-t-4">
+ <el-space wrap>
+ <el-tag
+ type="default"
+ v-for="user in taskStatistic.progressPerUser"
+ :key="user.userId"
+ >
+ <!-- {{
+ `${user.userName}锛氬贰鏌ラ噺 ${
+ user.completeTaskNum
+ }锛屽嵆鏃舵暣鏀圭巼 ${formatPercent(
+ user.changedProblemNumOnTime / user.totalProblemNum
+ )}锛屽钩鍧囪�楁椂 ${
+ user.avgInspectionTime ? user.avgInspectionTime : '--'
+ }`
+ }} -->
+ {{
+ `${user.userName}锛�${
+ user.completeTaskNum
+ } | ${formatPercent(
+ user.changedProblemNumOnTime / user.totalProblemNum
+ )} | ${
+ user.avgInspectionTime ? user.avgInspectionTime : '--'
+ }`
+ }}
+ </el-tag>
+ </el-space>
+ </el-row>
+ </div>
</template>
<template #date-cell="{ data }">
<div :class="calendarDayClz(data.day)">
<div style="background-color: #f8f4f4">{{ getDay(data.day) }}</div>
<template v-if="computeDayTask(data.day)">
- <!-- <el-divider></el-divider> -->
- <el-row justify="space-between" class="m-t-16">
+ <el-row
+ v-if="computeDayTask(data.day).totalTaskNum > 0"
+ justify="space-between"
+ >
<el-space direction="vertical">
- <el-text size="small">鎬昏</el-text>
- <el-text>{{ computeDayTask(data.day).totalTaskNum }}</el-text>
+ <el-text size="small" tag="b">宸℃煡閲�</el-text>
+ <el-text size="small"
+ >{{ computeDayTask(data.day).completeTaskNum }} /
+ {{ computeDayTask(data.day).totalTaskNum }}</el-text
+ >
</el-space>
<el-space direction="vertical">
- <el-text size="small">瀹屾垚</el-text>
- <el-text>{{ computeDayTask(data.day).completeTaskNum }}</el-text>
+ <el-text size="small" tag="b">缁煎悎鏁存敼鐜�</el-text>
+ <el-text size="small">{{
+ formatPercent(
+ computeDayTask(data.day).changedProblemNum /
+ computeDayTask(data.day).totalProblemNum
+ )
+ }}</el-text>
</el-space>
- <el-space direction="vertical">
- <el-text size="small">鏁存敼</el-text>
- <el-text>{{ computeDayTask(data.day).changedTaskNum }}</el-text>
- </el-space>
- <!-- <el-statistic title="鎬昏" :value="computeDayTask(data.day).totalTaskNum" />
- <el-statistic title="瀹屾垚" :value="computeDayTask(data.day).completeTaskNum" />
- <el-statistic title="鏁存敼" :value="computeDayTask(data.day).changedTaskNum" /> -->
</el-row>
- <!-- <div>浠诲姟鎬昏锛歿{ computeDayTask(data.day).totalTaskNum }}</div>
- <div>浠诲姟瀹屾垚锛歿{ computeDayTask(data.day).completeTaskNum }}</div>
- <div>浠诲姟鏁存敼锛歿{ computeDayTask(data.day).changedTaskNum }}</div> -->
+ <div style="border-top: 1px solid #0000002f" class="m-t-4"></div>
+ <div
+ v-for="item in computeDayTask(data.day).progressPerUser"
+ :key="item.userId"
+ class="m-t-4"
+ >
+ <el-row justify="space-between">
+ <el-text
+ title="宸℃煡浜哄憳"
+ size="small"
+ :type="
+ selectedUsers.includes(item.userName) ? 'primary' : 'info'
+ "
+ :tag="selectedUsers.includes(item.userName) ? 'b' : 'span'"
+ >{{ item.userName }}</el-text
+ >
+ </el-row>
+ <el-row justify="space-between">
+ <!-- <el-space> -->
+ <el-text
+ title="宸℃煡閲�"
+ size="small"
+ style="text-align: center; flex: 1"
+ :type="
+ selectedUsers.includes(item.userName) ? 'primary' : 'info'
+ "
+ :tag="selectedUsers.includes(item.userName) ? 'b' : 'span'"
+ >{{ item.completeTaskNum }}</el-text
+ >
+ <el-text
+ title="鍗虫椂鏁存敼鐜�"
+ size="small"
+ style="text-align: center; flex: 1"
+ :type="
+ selectedUsers.includes(item.userName) ? 'primary' : 'info'
+ "
+ :tag="selectedUsers.includes(item.userName) ? 'b' : 'span'"
+ >{{
+ formatPercent(
+ item.changedProblemNumOnTime / item.totalProblemNum
+ )
+ }}</el-text
+ >
+ <el-text
+ title="骞冲潎鑰楁椂"
+ size="small"
+ style="text-align: center; flex: 1"
+ :type="
+ selectedUsers.includes(item.userName) ? 'primary' : 'info'
+ "
+ :tag="selectedUsers.includes(item.userName) ? 'b' : 'span'"
+ >{{
+ timeUtil.formatSecondsToChinese(item.avgInspectionTime)
+ }}</el-text
+ >
+ <!-- </el-space> -->
+ </el-row>
+ </div>
</template>
</div>
</template>
@@ -48,25 +164,23 @@
import { ref, computed, onMounted, watch } from 'vue';
import taskApi from '@/api/fysp/taskApi';
import dayjs from 'dayjs';
+import timeUtil from '@/utils/time-util';
const props = defineProps({
task: {
type: Object,
default: () => {}
+ },
+ dayTaskList: {
+ type: Array,
+ default: () => []
}
});
const emit = defineEmits(['dateChange']);
// 閫変腑鏃ユ湡
+const selectedUsers = ref([]);
+// const dateValue = ref(new Date());
const dateValue = ref();
-// 鏃ュ巻鏍囬
-const title = computed(() => {
- if (props.task) {
- // return `${props.task.name}璁″垝`;
- return `宸℃煡璁″垝`;
- } else {
- return '';
- }
-});
// 鏃ュ巻鑼冨洿
const startDay = computed(() => dayjs(props.task.starttime));
const endDay = computed(() => dayjs(props.task.endtime));
@@ -74,7 +188,6 @@
startDay.value.toDate(),
endDay.value.toDate()
]);
-// const dateRange = computed(() => [new Date(2024, 4, 27), new Date(2024, 5, 30)]);
// 鏃ユ湡鏄惁鍦ㄤ换鍔¤寖鍥村唴
function isDayEnable(day) {
@@ -98,22 +211,32 @@
/********************** 浠诲姟鏁版嵁 *********************************/
-// 鑾峰彇鏃ヤ换鍔$粺璁′俊鎭�
-const dayTaskLoading = ref(false);
-const dayTaskList = ref([]);
-function fetchDayTasks() {
- dayTaskLoading.value = true;
- return taskApi
- .fetchDayTasks(props.task.tguid)
- .then((res) => {
- dayTaskList.value = res;
- // 濡傛灉宸查�夋棩鏈熷瓨鍦紝鍦ㄩ噸鏂拌幏鍙栨棩浠诲姟缁熻淇℃伅鍚庯紝鍐嶆瑙﹀彂鐐瑰嚮浜嬩欢
- if (dateValue.value) {
- onDateChange(dateValue.value)
- }
- })
- .finally(() => (dayTaskLoading.value = false));
-}
+watch(
+ () => props.dayTaskList,
+ (nV, oV) => {
+ if (nV && dateValue.value) {
+ onDateChange(dateValue.value);
+ }
+ },
+ { immediate: false }
+);
+
+// // 鑾峰彇鏃ヤ换鍔$粺璁′俊鎭�
+// const dayTaskLoading = ref(false);
+// const dayTaskList = ref([]);
+// function fetchDayTasks() {
+// dayTaskLoading.value = true;
+// return taskApi
+// .fetchDayTasks(props.task.tguid)
+// .then((res) => {
+// dayTaskList.value = res;
+// // 濡傛灉宸查�夋棩鏈熷瓨鍦紝鍦ㄩ噸鏂拌幏鍙栨棩浠诲姟缁熻淇℃伅鍚庯紝鍐嶆瑙﹀彂鐐瑰嚮浜嬩欢
+// if (dateValue.value) {
+// onDateChange(dateValue.value);
+// }
+// })
+// .finally(() => (dayTaskLoading.value = false));
+// }
// 鏃ヤ换鍔℃暟鎹睍绀�
const compMap = new Map();
@@ -123,7 +246,7 @@
return compMap.get(key).value;
}
const result = computed(() => {
- return dayTaskList.value.find((v) => {
+ return props.dayTaskList.find((v) => {
return dayjs(v.date).isSame(dayjs(day));
});
});
@@ -135,33 +258,72 @@
if (isDayEnable(e)) {
const day = dayjs(e).format('YYYY-MM-DD');
const t = computeDayTask(day);
- emit('dateChange', t);
+ emit('dateChange', t, day);
}
}
// 鎬讳换鍔$粺璁�
const taskStatistic = computed(() => {
- const res = { total: 0, complete: 0, changed: 0 };
- dayTaskList.value.forEach((e) => {
+ // const resMap = new Map()
+ const res = {
+ total: 0,
+ complete: 0,
+ changed: 0,
+ changedProblemNum: 0,
+ totalProblemNum: 0
+ };
+ const userMap = new Map();
+ props.dayTaskList.forEach((e) => {
res.total += e.totalTaskNum;
res.complete += e.completeTaskNum;
res.changed += e.changedTaskNum;
+ res.changedProblemNum += e.changedProblemNum;
+ res.totalProblemNum += e.totalProblemNum;
+ e.progressPerUser.forEach((user) => {
+ if (!userMap.has(user.userId)) {
+ userMap.set(user.userId, {
+ userName: user.userName,
+ completeTaskNum: 0,
+ changedProblemNumOnTime: 0,
+ totalProblemNum: 0,
+ totalInspectionTime: 0,
+ dayTaskNum: 0
+ });
+ }
+ const userItem = userMap.get(user.userId);
+ userItem.completeTaskNum += user.completeTaskNum;
+ userItem.changedProblemNumOnTime += user.changedProblemNumOnTime;
+ userItem.totalProblemNum += user.totalProblemNum;
+ userItem.totalInspectionTime += user.avgInspectionTime;
+ userItem.dayTaskNum++;
+ });
});
+ res.progressPerUser = Array.from(userMap.values()).map((user) => ({
+ ...user,
+ completeTaskNum: Math.round(user.completeTaskNum * 100) / 100,
+ avgInspectionTime: timeUtil.formatSecondsToChinese(
+ user.totalInspectionTime / user.dayTaskNum
+ )
+ }));
return res;
});
+
+const formatPercent = (num) => {
+ return isNaN(num) ? '0%' : parseInt(num * 100) + '%';
+};
/********************** 鍒濆鍖� *********************************/
-watch(
- () => props.task,
- (nV) => {
- if (nV && nV.tguid) {
- fetchDayTasks();
- }
- },
- { immediate: true }
-);
+// watch(
+// () => props.task,
+// (nV) => {
+// if (nV && nV.tguid) {
+// fetchDayTasks();
+// }
+// },
+// { immediate: true }
+// );
-defineExpose({ fetchDayTasks });
+// defineExpose({ fetchDayTasks });
</script>
<style scoped>
.li-01 {
@@ -179,16 +341,16 @@
top: 5px;
}
-::v-deep .el-calendar-table .el-calendar-day {
+:deep(.el-calendar-table .el-calendar-day) {
height: initial;
padding: initial;
}
-::v-deep .el-calendar-table .el-calendar-day:hover {
+:deep(.el-calendar-table .el-calendar-day:hover) {
background-color: transparent;
}
-/* ::v-deep .el-calendar-table td.is-selected {
+/* :deep(.el-calendar-table td.is-selected) {
background-color: initial;
} */
@@ -215,15 +377,15 @@
cursor: not-allowed;
}
-/* ::v-deep .el-calendar-table tr td:first-child {
+/* :deep(.el-calendar-table tr td:first-child) {
border-left: none !important;
} */
-/* ::v-deep .el-calendar-table tr:first-child td {
+/* :deep(.el-calendar-table tr:first-child td) {
border-top: none;
} */
-/* ::v-deep .el-calendar-table td {
+/* :deep(.el-calendar-table td) {
border-bottom: none;
border-right: none;
vertical-align: top;
@@ -231,7 +393,7 @@
transition: background-color 0.2s ease;
} */
-::v-deep .el-calendar-table thead th {
+:deep(.el-calendar-table thead th) {
padding: 12px 0;
color: #606266;
font-weight: normal;
--
Gitblit v1.9.3