| | |
| | | <template> |
| | | <el-calendar |
| | | v-model="dateValue" |
| | | :range="dateRange" |
| | | @update:model-value="onDateChange" |
| | | > |
| | | <el-calendar v-model="dateValue" :range="dateRange" @update:model-value="onDateChange"> |
| | | <template #header="{ date }"> |
| | | <div style="width: 100%"> |
| | | <el-row justify="space-between"> |
| | | <el-space> |
| | | <el-tag type="default" |
| | | >巡查量:{{ |
| | | `${taskStatistic.complete}/${taskStatistic.total}` |
| | | }}</el-tag |
| | | >巡查量:{{ `${taskStatistic.complete}/${taskStatistic.total}` }}</el-tag |
| | | > |
| | | <el-tag type="default" |
| | | <!-- <el-tag type="default" |
| | | >当日整改率:{{ |
| | | formatPercent( |
| | | taskStatistic.changedProblemNumOnTime / |
| | |
| | | taskStatistic.totalProblemNum |
| | | ) |
| | | }}</el-tag |
| | | > |
| | | > --> |
| | | <el-tag type="default" |
| | | >综合整改率:{{ |
| | | formatPercent( |
| | | taskStatistic.changedProblemNum / |
| | | taskStatistic.totalProblemNum |
| | | ) |
| | | >整改率:{{ |
| | | formatPercent(taskStatistic.changedProblemNum / taskStatistic.totalProblemNum) |
| | | }}</el-tag |
| | | > |
| | | <!-- <el-tag type="default">整改:{{ taskStatistic.changed }}</el-tag> --> |
| | | </el-space> |
| | | <el-space> |
| | | <!-- <el-space> |
| | | <el-text>聚焦用户:</el-text> |
| | | <el-select |
| | | v-model="selectedUsers" |
| | |
| | | :value="user.userName" |
| | | /> |
| | | </el-select> |
| | | </el-space> |
| | | </el-space> --> |
| | | </el-row> |
| | | <el-row class="m-t-4"> |
| | | <!-- <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 |
| | |
| | | }} |
| | | </el-tag> |
| | | </el-space> |
| | | </el-row> |
| | | </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-row |
| | | v-if="computeDayTask(data.day).totalTaskNum > 0" |
| | | justify="space-between" |
| | | > |
| | | <el-row v-if="computeDayTask(data.day).totalTaskNum > 0" justify="space-between"> |
| | | <el-space direction="vertical"> |
| | | <el-text size="small" tag="b">巡查量</el-text> |
| | | <el-text size="small" |
| | |
| | | <el-text size="small">{{ |
| | | formatPercent( |
| | | computeDayTask(data.day).changedProblemNum / |
| | | computeDayTask(data.day).totalProblemNum |
| | | computeDayTask(data.day).totalProblemNum, |
| | | ) |
| | | }}</el-text> |
| | | </el-space> |
| | |
| | | <el-text |
| | | title="巡查人员" |
| | | size="small" |
| | | :type=" |
| | | selectedUsers.includes(item.userName) ? 'primary' : 'info' |
| | | " |
| | | :type="selectedUsers.includes(item.userName) ? 'primary' : 'info'" |
| | | :tag="selectedUsers.includes(item.userName) ? 'b' : 'span'" |
| | | >{{ item.userName }}</el-text |
| | | > |
| | |
| | | title="巡查量" |
| | | size="small" |
| | | style="text-align: center; flex: 1" |
| | | :type=" |
| | | selectedUsers.includes(item.userName) ? 'primary' : 'info' |
| | | " |
| | | :type="selectedUsers.includes(item.userName) ? 'primary' : 'info'" |
| | | :tag="selectedUsers.includes(item.userName) ? 'b' : 'span'" |
| | | >{{ item.completeTaskNum }}</el-text |
| | | > |
| | |
| | | title="当日整改率" |
| | | size="small" |
| | | style="text-align: center; flex: 1" |
| | | :type=" |
| | | selectedUsers.includes(item.userName) ? 'primary' : 'info' |
| | | " |
| | | :type="selectedUsers.includes(item.userName) ? 'primary' : 'info'" |
| | | :tag="selectedUsers.includes(item.userName) ? 'b' : 'span'" |
| | | >{{ |
| | | formatPercent( |
| | | item.changedProblemNumOnTime / item.totalProblemNum |
| | | ) |
| | | }}</el-text |
| | | >{{ 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' |
| | | " |
| | | :type="selectedUsers.includes(item.userName) ? 'primary' : 'info'" |
| | | :tag="selectedUsers.includes(item.userName) ? 'b' : 'span'" |
| | | >{{ |
| | | timeUtil.formatSecondsToChinese(item.avgInspectionTime) |
| | | }}</el-text |
| | | >{{ timeUtil.formatSecondsToChinese(item.avgInspectionTime) }}</el-text |
| | | > |
| | | <!-- </el-space> --> |
| | | </el-row> |
| | |
| | | </el-calendar> |
| | | </template> |
| | | <script setup> |
| | | import { ref, computed, onMounted, watch } from 'vue'; |
| | | import taskApi from '@/api/fysp/taskApi'; |
| | | import dayjs from 'dayjs'; |
| | | import timeUtil from '@/utils/time-util'; |
| | | 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: () => {} |
| | | default: () => {}, |
| | | }, |
| | | dayTaskList: { |
| | | type: Array, |
| | | default: () => [] |
| | | } |
| | | }); |
| | | const emit = defineEmits(['dateChange']); |
| | | default: () => [], |
| | | }, |
| | | }) |
| | | const emit = defineEmits(['dateChange']) |
| | | // 选中日期 |
| | | const selectedUsers = ref([]); |
| | | const selectedUsers = ref([]) |
| | | // const dateValue = ref(new Date()); |
| | | const dateValue = ref(); |
| | | const dateValue = ref() |
| | | // 日历范围 |
| | | const startDay = computed(() => dayjs(props.task.starttime)); |
| | | const endDay = computed(() => dayjs(props.task.endtime)); |
| | | const dateRange = computed(() => [ |
| | | startDay.value.toDate(), |
| | | endDay.value.toDate() |
| | | ]); |
| | | const startDay = computed(() => dayjs(props.task.starttime)) |
| | | const endDay = computed(() => dayjs(props.task.endtime)) |
| | | const dateRange = computed(() => [startDay.value.toDate(), endDay.value.toDate()]) |
| | | |
| | | // 日期是否在任务范围内 |
| | | function isDayEnable(day) { |
| | | const _day = dayjs(day); |
| | | return ( |
| | | _day.isSameOrAfter(startDay.value, 'day') && |
| | | _day.isSameOrBefore(endDay.value, 'day') |
| | | ); |
| | | const _day = dayjs(day) |
| | | return _day.isSameOrAfter(startDay.value, 'day') && _day.isSameOrBefore(endDay.value, 'day') |
| | | } |
| | | |
| | | /********************** 日期样式 *********************************/ |
| | | function calendarDayClz(day) { |
| | | return ( |
| | | 'calendar-day ' + |
| | | (isDayEnable(day) ? 'calendar-day-enable' : 'calendar-day-disable') |
| | | ); |
| | | return 'calendar-day ' + (isDayEnable(day) ? 'calendar-day-enable' : 'calendar-day-disable') |
| | | } |
| | | function getDay(day) { |
| | | return day.split('-').splice(1, 2).join('-'); |
| | | return day.split('-').splice(1, 2).join('-') |
| | | } |
| | | |
| | | /********************** 任务数据 *********************************/ |
| | |
| | | () => props.dayTaskList, |
| | | (nV, oV) => { |
| | | if (nV && dateValue.value) { |
| | | onDateChange(dateValue.value); |
| | | onDateChange(dateValue.value) |
| | | } |
| | | }, |
| | | { immediate: false } |
| | | ); |
| | | { immediate: false }, |
| | | ) |
| | | |
| | | // // 获取日任务统计信息 |
| | | // const dayTaskLoading = ref(false); |
| | |
| | | // } |
| | | |
| | | // 日任务数据展示 |
| | | const compMap = new Map(); |
| | | const compMap = new Map() |
| | | function computeDayTask(day) { |
| | | const key = props.task.tguid + day; |
| | | const key = props.task.tguid + day |
| | | if (compMap.has(key)) { |
| | | return compMap.get(key).value; |
| | | return compMap.get(key).value |
| | | } |
| | | const result = computed(() => { |
| | | return props.dayTaskList.find((v) => { |
| | | return dayjs(v.date).isSame(dayjs(day)); |
| | | }); |
| | | }); |
| | | compMap.set(key, result); |
| | | return result.value; |
| | | return dayjs(v.date).isSame(dayjs(day)) |
| | | }) |
| | | }) |
| | | compMap.set(key, result) |
| | | return result.value |
| | | } |
| | | |
| | | function onDateChange(e) { |
| | | if (isDayEnable(e)) { |
| | | const day = dayjs(e).format('YYYY-MM-DD'); |
| | | const t = computeDayTask(day); |
| | | emit('dateChange', t, day); |
| | | const day = dayjs(e).format('YYYY-MM-DD') |
| | | const t = computeDayTask(day) |
| | | emit('dateChange', t, day) |
| | | } |
| | | } |
| | | |
| | |
| | | changedProblemNum: 0, |
| | | totalProblemNum: 0, |
| | | changedProblemNumOnTime: 0, |
| | | efficientChangedProNum: 0 |
| | | }; |
| | | const userMap = new Map(); |
| | | efficientChangedProNum: 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; |
| | | 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, { |
| | |
| | | changedProblemNumOnTime: 0, |
| | | totalProblemNum: 0, |
| | | totalInspectionTime: 0, |
| | | dayTaskNum: 0 |
| | | }); |
| | | dayTaskNum: 0, |
| | | }) |
| | | } |
| | | res.changedProblemNumOnTime += user.changedProblemNumOnTime |
| | | res.efficientChangedProNum += user.efficientChangedProNum |
| | | const userItem = userMap.get(user.userId); |
| | | userItem.completeTaskNum += user.completeTaskNum; |
| | | userItem.changedProblemNumOnTime += user.changedProblemNumOnTime; |
| | | userItem.totalProblemNum += user.totalProblemNum; |
| | | userItem.totalInspectionTime += user.avgInspectionTime ?? 0; |
| | | userItem.dayTaskNum++; |
| | | }); |
| | | }); |
| | | const userItem = userMap.get(user.userId) |
| | | userItem.completeTaskNum += user.completeTaskNum |
| | | userItem.changedProblemNumOnTime += user.changedProblemNumOnTime |
| | | userItem.totalProblemNum += user.totalProblemNum |
| | | userItem.totalInspectionTime += user.avgInspectionTime ?? 0 |
| | | 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; |
| | | }); |
| | | avgInspectionTime: timeUtil.formatSecondsToChinese(user.totalInspectionTime / user.dayTaskNum), |
| | | })) |
| | | return res |
| | | }) |
| | | |
| | | const formatPercent = (num) => { |
| | | return isNaN(num) ? '0%' : parseInt(num * 100) + '%'; |
| | | }; |
| | | return isNaN(num) ? '0%' : parseInt(num * 100) + '%' |
| | | } |
| | | /********************** 初始化 *********************************/ |
| | | |
| | | // watch( |