riku
5 天以前 f19e5267cc23b1c714dc746239864f33ed715dd9
src/views/fysp/task/components/CompMonitorPlan.vue
@@ -5,39 +5,156 @@
    @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>
@@ -47,6 +164,7 @@
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: {
@@ -60,16 +178,9 @@
});
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));
@@ -77,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) {
@@ -154,14 +264,53 @@
// 总任务统计
const taskStatistic = computed(() => {
  const res = { total: 0, complete: 0, changed: 0 };
  // 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(
@@ -192,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;
} */
@@ -228,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;
@@ -244,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;