1. 新增巡查计划功能(待完成);
2. 完成任务的各场景下的分别移除和添加;
已修改6个文件
已添加3个文件
533 ■■■■■ 文件已修改
src/api/fysp/taskApi.js 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components.d.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/list-item/ItemSubTask.vue 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/task/MonitorObjEdit.vue 42 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/task/MonitorPlanEdit.vue 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/task/TaskManage.vue 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/task/components/CompMonitorObj.vue 44 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/task/components/CompMonitorPlan.vue 225 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/fysp/taskApi.js
@@ -50,6 +50,18 @@
  },
  /**
   * èŽ·å–æ¯æ—¥ä»»åŠ¡ç»Ÿè®¡ä¿¡æ¯
   * @param {String} topTaskId æ€»ä»»åС䏻键id
   * @param {String} userId ç”¨æˆ·id,当用户类型userType为1(监管用户)时,会根据用户id获取其权限内的统计信息
   * @param {String} userType ç”¨æˆ·ç±»åž‹ï¼Œ0:管理员;1:监管用户;2:政府部门;3:企业
   */
  fetchDayTasks(topTaskId, userId = '', userType = '0') {
    return $fysp
      .get(`task/dayTask/${topTaskId}?userId=${userId}&userType=${userType}`)
      .then((res) => res.data);
  },
  /**
   * èŽ·å–å­ä»»åŠ¡ç»Ÿè®¡ä¿¡æ¯
   */
  getSubtaskSummary({ topTaskId = undefined, sceneTypeId = undefined }) {
@@ -64,6 +76,17 @@
  },
  /**
   * èŽ·å–å…·ä½“å­ä»»åŠ¡ä¿¡æ¯
   * @param {String} dayTaskId æ—¥ä»»åС䏻键id
   * @param {String} userId ç”¨æˆ·id,当用户类型userType为1(监管用户)时,会根据用户id获取其权限内的统计信息
   * @param {String} userType ç”¨æˆ·ç±»åž‹ï¼Œ0:管理员;1:监管用户;2:政府部门;3:企业
   */
  fetchSubtaskByDayTask(dayTaskId, userId = '', userType = '0') {
    const params = `?dayTaskId=${dayTaskId}&userId=${userId}&userType=${userType}`;
    return $fysp.get(`subtask/byDayTaskId${params}`).then((res) => res.data);
  },
  /**
   * èŽ·å–å­ä»»åŠ¡é—®é¢˜è¯¦æƒ…
   */
  getProBySubtask(id) {
src/components.d.ts
@@ -22,6 +22,7 @@
    ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem']
    ElButton: typeof import('element-plus/es')['ElButton']
    ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup']
    ElCalendar: typeof import('element-plus/es')['ElCalendar']
    ElCard: typeof import('element-plus/es')['ElCard']
    ElCascader: typeof import('element-plus/es')['ElCascader']
    ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
@@ -58,6 +59,7 @@
    ElSegmented: typeof import('element-plus/es')['ElSegmented']
    ElSelect: typeof import('element-plus/es')['ElSelect']
    ElSpace: typeof import('element-plus/es')['ElSpace']
    ElStatistic: typeof import('element-plus/es')['ElStatistic']
    ElStep: typeof import('element-plus/es')['ElStep']
    ElSteps: typeof import('element-plus/es')['ElSteps']
    ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
@@ -92,6 +94,7 @@
    Header: typeof import('./components/core/Header.vue')['default']
    ItemMonitorObj: typeof import('./components/list-item/ItemMonitorObj.vue')['default']
    ItemScene: typeof import('./components/list-item/ItemScene.vue')['default']
    ItemSubTask: typeof import('./components/list-item/ItemSubTask.vue')['default']
    ItemUser: typeof import('./components/list-item/ItemUser.vue')['default']
    MenuItems: typeof import('./components/core/MenuItems.vue')['default']
    RouterLink: typeof import('vue-router')['RouterLink']
src/components/list-item/ItemSubTask.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,38 @@
<template>
  <div class="wrapper">
    <div>
      <el-text truncated>{{ item.name }}</el-text>
    </div>
    <div>
      <el-space fill>
        <el-text truncated class="w-250px" size="small">{{ item.scenseaddress }}</el-text>
        <el-text truncated class="w-250px" size="small">{{
          $fm.formatYMDH(item.planstarttime)
        }}</el-text>
        <el-text truncated class="w-250px" size="small">{{ item.executorrealtimes }}</el-text>
      </el-space>
    </div>
    <el-row justify="end" style="margin-top: 4px">
      <slot :item="item"></slot>
    </el-row>
  </div>
</template>
<script setup>
/**
 * ç›‘管对象
 */
const props = defineProps({
  item: {
    type: Object,
    default: () => {}
  }
});
</script>
<style scoped>
.wrapper {
  /* width: 300px; */
  border: 1px solid var(--el-border-color);
  border-radius: var(--el-border-radius-base);
  padding: 4px 8px;
}
</style>
src/router/index.js
@@ -73,6 +73,12 @@
    component: () => import('@/views/fysp/task/MonitorObjEdit.vue')
  },
  {
    //监管任务计划编辑
    name: 'monitorPlanEdit',
    path: '/fysp/task/plan/edit',
    component: () => import('@/views/fysp/task/MonitorPlanEdit.vue')
  },
  {
    //问题审核
    name: 'procheck',
    path: '/fysp/procheck',
src/views/fysp/task/MonitorObjEdit.vue
@@ -1,7 +1,7 @@
<template>
  <el-affix :offset="60">
    <div class="page-header">
      <el-page-header @back="$router.back()">
      <el-page-header @back="goBack">
        <template #content>
          <span> æ€»ä»»åŠ¡ç¼–è¾‘ </span>
        </template>
@@ -24,10 +24,11 @@
      <el-divider />
      <CompMonitorObj
        :data="curMonitorObjList"
        show-delete
        show-btn
        v-model:tabName="curSceneType"
        v-model:showData="showMonitorObjList"
        @delete-item="deleteMov"
        :tabOptions="sceneTypeOptions"
        @item-click="deleteMov"
      >
      </CompMonitorObj>
    </el-col>
@@ -41,7 +42,6 @@
          <el-segmented v-model="curSceneType" :options="sceneTypeOptions" />
        </div>
        <FYInfoSearch
          label=""
          placeholder="请输入场景名称关键字"
          :data="showSceneList"
          :on-search="searchScene"
@@ -92,9 +92,14 @@
import svUserApi from '@/api/fysp/userApi';
import taskApi from '@/api/fysp/taskApi';
import sceneApi from '@/api/fysp/sceneApi';
import { ElMessage, ElNotification } from 'element-plus';
import { ElMessage, ElNotification, ElMessageBox } from 'element-plus';
export default {
  async beforeRouteLeave(to, from) {
    // åœ¨å¯¼èˆªç¦»å¼€æ¸²æŸ“该组件的对应路由时调用
    // ä¸Ž `beforeRouteUpdate` ä¸€æ ·ï¼Œå®ƒå¯ä»¥è®¿é—®ç»„件实例 `this`
    // return this.routerChangeCheck();
  },
  components: { CompMonitorObj },
  props: {},
  data() {
@@ -104,7 +109,6 @@
      // å½“前筛选的场景类型
      curSceneType: undefined,
      showMonitorObjList: [],
      // è¡Œæ”¿åŒºåˆ’
      area: {},
@@ -140,7 +144,7 @@
        return index == -1 && v.type == this.curSceneType;
      });
    },
    sceneTypeOptions(){
    sceneTypeOptions() {
      const list = [];
      this.sceneList.forEach((d) => {
        if (list.indexOf(d.type) == -1) list.push(d.type);
@@ -302,6 +306,30 @@
      // return Promise.all([p1, p2, p3]).finally(() => {
      //   this.saveLoading = false;
      // });
    },
    async goBack() {
      // const answer = await this.routerChangeCheck()
      // if (answer) {
      //   this.$router.back();
      // }
      this.$router.back();
    },
    async routerChangeCheck() {
      if (this.isEdit) {
        const answer = await ElMessageBox.confirm('是否放弃已修改的总任务?', '取消总任务修改', {
          confirmButtonText: '确认',
          cancelButtonText: '取消',
          type: 'warning'
        })
          .then(() => {
            return true;
          })
          .catch(() => {
            return false;
          });
        return answer;
      }
      return true;
    }
  },
  mounted() {
src/views/fysp/task/MonitorPlanEdit.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,99 @@
<template>
  <el-affix :offset="60">
    <div class="page-header">
      <el-page-header @back="goBack">
        <template #content>
          <span> è®¡åˆ’调整 </span>
        </template>
        <template #extra>
          <div>
            <el-button type="primary" :disabled="!isEdit" :loading="saveLoading" @click="saveEdit"
              >保存修改</el-button
            >
          </div>
        </template>
      </el-page-header>
      <el-divider />
    </div>
  </el-affix>
  <el-row gutter="20">
    <el-col :span="16">
      <el-affix :offset="140">
        <div>
          <el-text>监管计划</el-text>
        </div>
        <el-divider />
        <CompMonitorPlan :task="task" @date-change="onDateChange"></CompMonitorPlan>
      </el-affix>
    </el-col>
    <el-col :span="8">
      <el-row justify="space-between">
        <el-text>单日计划</el-text>
        <el-button type="success" size="small" @click="editTask">新增</el-button>
      </el-row>
      <el-divider />
      <ItemSubTask v-for="stask in curSubTaskList" :key="stask.guid" :item="stask">
        <template #default="{ item }">
          <el-button type="danger" size="small" @click="editTask">移除</el-button>
        </template>
      </ItemSubTask>
      <!-- <CompMonitorObj
        :data="curMonitorObjList"
        show-btn
        v-model:tabName="curSceneType"
        v-model:showData="showMonitorObjList"
        btn-name="添加"
        @item-click="deleteMov"
      >
      </CompMonitorObj> -->
    </el-col>
  </el-row>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import CompMonitorPlan from './components/CompMonitorPlan.vue';
import CompMonitorObj from './components/CompMonitorObj.vue';
import taskApi from '@/api/fysp/taskApi';
const route = useRoute();
const router = useRouter();
const curMonitorObjList = ref([]);
const task = ref({});
const curSceneType = ref({});
const showMonitorObjList = ref({});
const curSubTaskList = ref([]);
function onDateChange(dayTask) {
  if (dayTask) {
    fetchSubTask(dayTask.guid);
  } else {
    curSubTaskList.value = [];
  }
}
function fetchSubTask(dayTaskId) {
  taskApi.fetchSubtaskByDayTask(dayTaskId).then((res) => {
    curSubTaskList.value = res;
  });
}
onMounted(() => {
  // ç›‘管场景信息
  curMonitorObjList.value = JSON.parse(decodeURIComponent(route.query.data));
  // æ ¹æ®æ€»ä»»åŠ¡èŽ·å–è¡Œæ”¿åŒºåˆ’ä¿¡æ¯
  task.value = JSON.parse(decodeURIComponent(route.query.task));
});
function goBack() {
  router.back();
}
</script>
<style scoped>
.page-header {
  background-color: white;
}
</style>
src/views/fysp/task/TaskManage.vue
@@ -31,11 +31,17 @@
        class="el-scrollbar"
        v-loading="mainLoading"
      >
        <div><el-text>监管计划</el-text></div>
        <el-row justify="space-between">
          <div><el-text>监管计划</el-text></div>
          <el-button type="warning" size="small" @click="editPlan">计划调整</el-button>
          <CompMonitorPlan :task="curTask.data"></CompMonitorPlan>
        </el-row>
        <el-divider></el-divider>
        <el-button type="primary" size="small" @click="editTask">场景调整</el-button>
        <div><el-text>监管场景</el-text></div>
        <CompMonitorObj :data="curMonitorObjList" v-model:showData="showMonitorObjList"></CompMonitorObj>
        <el-row justify="space-between">
          <div><el-text>监管场景</el-text></div>
          <el-button type="warning" size="small" @click="editTask">场景调整</el-button>
        </el-row>
        <CompMonitorObj :data="curMonitorObjList"></CompMonitorObj>
        <!-- <div><el-text>监管场景</el-text></div>
        <div>
          <el-space wrap>
@@ -55,8 +61,19 @@
<script>
import taskApi from '@/api/fysp/taskApi';
import CompMonitorObj from './components/CompMonitorObj.vue';
import CompMonitorPlan from './components/CompMonitorPlan.vue';
export default {
  components: { CompMonitorObj },
  beforeRouteEnter(to, from, next) {
    // åœ¨æ¸²æŸ“该组件的对应路由被验证前调用
    // ä¸èƒ½èŽ·å–ç»„ä»¶å®žä¾‹ `this` ï¼
    // å› ä¸ºå½“守卫执行时,组件实例还没被创建!
    next((vm) => {
      if (from.name == 'monitorObjEdit' && vm.task) {
        vm.chooseTask(vm.task);
      }
    });
  },
  components: { CompMonitorObj, CompMonitorPlan },
  data() {
    return {
      formSearch: {
@@ -79,14 +96,14 @@
      curTask: {},
      //操作按钮
      buttons: [
        {
          name: '计划调整',
          color: 'success'
        },
        {
          name: '场景调整',
          color: 'warning'
        }
        // {
        //   name: '计划调整',
        //   color: 'success'
        // },
        // {
        //   name: '场景调整',
        //   color: 'warning'
        // }
      ]
    };
  },
@@ -143,6 +160,7 @@
      return type;
    },
    chooseTask(task) {
      this.task = task;
      this.sideLoading = false;
      this.mainLoading = true;
      taskApi
@@ -163,6 +181,15 @@
          task: encodeURIComponent(JSON.stringify(this.curTask.data))
        }
      });
    },
    editPlan(){
      this.$router.push({
        name: 'monitorPlanEdit',
        query: {
          data: encodeURIComponent(JSON.stringify(this.curMonitorObjList)),
          task: encodeURIComponent(JSON.stringify(this.curTask.data)),
        }
      });
    }
  },
  mounted() {
src/views/fysp/task/components/CompMonitorObj.vue
@@ -1,14 +1,14 @@
<template>
  <div>
    <el-segmented :model-value="tabName" :options="tabs" @change="tabChange" />
    <el-segmented :model-value="activeName" :options="activeTabs" @change="tabChange" />
  </div>
  <el-space wrap>
    <ItemMonitorObj v-for="obj in activeData" :key="obj.movid" :item="obj">
      <template #default="{ item }">
        <!-- <slot :item="item"></slot> -->
        <el-button v-if="showDelete" size="small" type="danger" @click="deleteMov(item)"
          >移除</el-button
        >
        <el-button v-if="showBtn" size="small" type="danger" @click="itemClick(item)">{{
          btnName
        }}</el-button>
      </template>
    </ItemMonitorObj>
  </el-space>
@@ -26,12 +26,17 @@
      type: String,
      default: defaultTabName
    },
    tabOptions: Array,
    showData: Array,
    // æ˜¯å¦æ·»åŠ é»˜è®¤çš„å…¨éƒ¨é€‰é¡¹
    allOption: Boolean,
    showDelete: Boolean
    showBtn: Boolean,
    btnName: {
      type: String,
      default: '移除'
    }
  },
  emits: ['update:tabName', 'update:showData', 'deleteItem'],
  emits: ['update:tabName', 'update:showData', 'itemClick'],
  data() {
    return {
      activeName: defaultTabName,
@@ -41,11 +46,18 @@
  computed: {
    activeData() {
      const list = this.data.filter((v) => {
        // return this.activeName == defaultTabName || v.sceneType == this.activeName;
        return this.tabName == defaultTabName || v.sceneType == this.tabName;
        return this.activeName == defaultTabName || v.sceneType == this.activeName;
        // return this.tabName == defaultTabName || v.sceneType == this.tabName;
      });
      this.$emit('update:showData', list);
      return list;
    },
    activeTabs() {
      if (this.tabOptions) {
        return this.tabOptions;
      } else {
        return this.tabs;
      }
    }
  },
  watch: {
@@ -60,11 +72,16 @@
    tabs: {
      handler(nV, oV) {
        if (nV != oV && nV.length > 0) {
          // this.activeName = nV[0];
          this.tabChange(nV);
          this.activeName = nV[0];
          this.tabChange(nV[0]);
        }
      },
      immediate: true
    },
    tabName(nV, oV) {
      if (nV != oV) {
        this.activeName = nV;
      }
    }
  },
  methods: {
@@ -73,13 +90,14 @@
      dataList.forEach((d) => {
        if (list.indexOf(d.sceneType) == -1) list.push(d.sceneType);
      });
      this.tabs = list;
      this.tabs = list.sort();
    },
    tabChange(tabName) {
      this.activeName = tabName;
      this.$emit('update:tabName', tabName);
    },
    deleteMov(item) {
      this.$emit('deleteItem', item);
    itemClick(item) {
      this.$emit('itemClick', item);
    }
  }
};
src/views/fysp/task/components/CompMonitorPlan.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,225 @@
<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> -->
    </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-space direction="vertical">
              <el-text size="small">总计</el-text>
              <el-text>{{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-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> -->
        </template>
      </div>
    </template>
  </el-calendar>
</template>
<script setup>
import { ref, computed, onMounted, watch } from 'vue';
import taskApi from '@/api/fysp/taskApi';
import dayjs from 'dayjs';
const props = defineProps({
  task: {
    type: Object,
    default: () => {}
  }
});
const emit = defineEmits(['dateChange'])
// é€‰ä¸­æ—¥æœŸ
const dateValue = ref(new Date());
// æ—¥åŽ†æ ‡é¢˜
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));
const dateRange = computed(() => [startDay.value.toDate(), endDay.value.toDate()]);
// const dateRange = computed(() => [new Date(2024, 4, 27), new Date(2024, 5, 30)]);
// æ—¥æœŸæ˜¯å¦åœ¨ä»»åŠ¡èŒƒå›´å†…
function isDayEnable(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');
}
function getDay(day) {
  return day.split('-').splice(1, 2).join('-');
}
/********************** ä»»åŠ¡æ•°æ® *********************************/
// èŽ·å–æ—¥ä»»åŠ¡ç»Ÿè®¡ä¿¡æ¯
const dayTaskLoading = ref(false);
const dayTaskList = ref([]);
function fetchDayTasks(topTaskId) {
  dayTaskLoading.value = true;
  taskApi
    .fetchDayTasks(topTaskId)
    .then((res) => {
      dayTaskList.value = res;
    })
    .finally(() => (dayTaskLoading.value = false));
}
// æ—¥ä»»åŠ¡æ•°æ®å±•ç¤º
const compMap = new Map();
function computeDayTask(day) {
  const key = props.task.tguid + day;
  if (compMap.has(key)) {
    return compMap.get(key).value;
  }
  const result = computed(() => {
    return dayTaskList.value.find((v) => {
      return dayjs(v.date).isSame(dayjs(day));
    });
  });
  compMap.set(key, result);
  return result.value;
}
function onDateChange(e) {
  const day = dayjs(e).format('YYYY-MM-DD')
  const t = computeDayTask(day)
  console.log(t);
  emit('dateChange', t)
}
// æ€»ä»»åŠ¡ç»Ÿè®¡
const taskStatistic = computed(() => {
  const res = { total: 0, complete: 0, changed: 0 };
  dayTaskList.value.forEach((e) => {
    res.total += e.totalTaskNum;
    res.complete += e.completeTaskNum;
    res.changed += e.changedTaskNum;
  });
  return res;
});
/********************** åˆå§‹åŒ– *********************************/
watch(
  () => props.task,
  (nV) => {
    if (nV.tguid) {
      fetchDayTasks(nV.tguid);
    }
  },
  { immediate: true }
);
</script>
<style scoped>
.li-01 {
  width: 31px !important;
  height: 31px;
  background: #fff !important;
  color: #001529 !important;
  border: 1.5px solid #25de9d;
  border-radius: 50%;
  margin-left: 50%;
  transform: translate(-15px);
  line-height: 30px;
  text-align: center;
  font-size: 16px;
  top: 5px;
}
::v-deep .el-calendar-table .el-calendar-day {
  height: initial;
  padding: initial;
}
::v-deep .el-calendar-table .el-calendar-day:hover {
  background-color: transparent;
}
/* ::v-deep .el-calendar-table td.is-selected {
  background-color: initial;
} */
.calendar-day {
  /* text-align: center;
  line-height: 30px;
  width: 30px;
  height: 30px;
  border: 1px solid rgb(172, 165, 165);
  border-radius: 50%; */
  padding: 8px;
  height: var(--el-calendar-cell-width);
}
.calendar-day-enable {
}
.calendar-day-enable:hover {
  background-color: var(--el-calendar-selected-bg-color);
}
.calendar-day-disable {
  color: var(--el-text-color-disabled);
  cursor: not-allowed;
}
/* ::v-deep .el-calendar-table tr td:first-child {
  border-left: none !important;
} */
/* ::v-deep .el-calendar-table tr:first-child td {
  border-top: none;
} */
/* ::v-deep .el-calendar-table td {
  border-bottom: none;
  border-right: none;
  vertical-align: top;
  -webkit-transition: background-color 0.2s ease;
  transition: background-color 0.2s ease;
} */
::v-deep .el-calendar-table thead th {
  padding: 12px 0;
  color: #606266;
  font-weight: normal;
  background-color: #faeaea;
}
</style>