lxf 2 лет назад
Родитель
Сommit
cb9fbb3ee7
1 измененных файлов с 690 добавлено и 0 удалено
  1. 690 0
      src/views/oa/work/dailyPaper/index.vue

+ 690 - 0
src/views/oa/work/dailyPaper/index.vue

@@ -0,0 +1,690 @@
+<template>
+  <div style="margin: 20px">
+    <div style="background: #fff; padding: 20px; width: 100%; display: flex; justify-content: space-between">
+      <div class="title commons-title" style="margin-bottom: 0">员工日报</div>
+      <div style="display: flex">
+        <el-input placeholder="请输入关键字" suffix-icon="search" size="mini" v-model="sourceList.pagination.keyword" @change="searchList()"> </el-input>
+        <el-button type="primary" style="margin-left: 10px" size="default" @click="newDaily">新建日报</el-button>
+      </div>
+    </div>
+    <div class="outer-layer">
+      <div class="left">
+        <el-calendar v-model="date" ref="calendar">
+          <template #header="{ date }">
+            <span>{{ date }}</span>
+            <el-button-group>
+              <el-icon style="cursor: pointer" @click="selectDate('prev-month')"><ArrowLeft /></el-icon>
+              <el-icon style="cursor: pointer" @click="selectDate('next-month')"><ArrowRight /></el-icon>
+            </el-button-group>
+          </template>
+        </el-calendar>
+        <div style="margin: 20px 0 0 0">
+          <el-icon style="transform: translateY(3px)"><Document /></el-icon>
+          <span style="margin-left: 8px">日报</span>
+        </div>
+        <el-menu :default-active="menuDefault" class="el-menu-vertical-demo" style="padding: 10px 0" @select="handleSelectMenu">
+          <el-menu-item index="1">
+            <span>我发出的日报</span>
+          </el-menu-item>
+          <el-menu-item index="2">
+            <span>收到的日报</span>
+          </el-menu-item>
+          <el-menu-item index="3">
+            <span>今日日报汇报情况</span>
+          </el-menu-item>
+        </el-menu>
+        <div style="padding: 20px 0 10px 0; border-top: 1px solid #eee">
+          <el-icon style="transform: translateY(3px)"><Timer /></el-icon>
+          <span style="margin-left: 8px">定时日报</span>
+        </div>
+      </div>
+      <div class="right">
+        <div style="height: calc(100vh - 100px - 72px - 60px - 40px); overflow-y: auto; margin: 20px" v-if="newStatus">
+          <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="submit">
+            <template #productPic>
+              <div>
+                <div>
+                  <el-upload
+                    v-model:fileList="imgList"
+                    action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
+                    :data="uploadData"
+                    list-type="picture-card"
+                    :before-upload="uploadPicture"
+                    :limit="5"
+                    accept=".gif, .jpeg, .jpg, .png">
+                    <el-icon><Plus /></el-icon>
+                  </el-upload>
+                </div>
+                <div style="color: #909399">建议尺寸800*800, 最多5张. 单个图片不得超过3M, 格式gif、jpeg、jpg、png</div>
+              </div>
+            </template>
+            <template #productFile>
+              <div style="width: 100%">
+                <el-upload
+                  v-model:fileList="attachmentList"
+                  action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
+                  :data="uploadData"
+                  :before-upload="uploadFile"
+                  accept=".pdf">
+                  <el-button>上传文件</el-button>
+                  <span style="color: #909399; margin-left: 8px">上传格式为pdf文件</span>
+                </el-upload>
+              </div>
+            </template>
+            <template #recipient>
+              <div style="width: 100%">
+                <el-select v-model="dailyReportDetailsList" multiple class="m-2" placeholder="Select" size="large" style="width: 100%">
+                  <el-option v-for="item in userList" :key="item.userId" :label="item.userName" :value="item.userId" />
+                </el-select>
+              </div>
+            </template>
+            <template #more>
+              <div style="width: 100%">
+                <el-checkbox v-model="formData.data.isVisibleToRecipient" :true-label="1" :false-label="0" label="仅接收人可见, 不可转发" size="large" />
+              </div>
+            </template>
+          </byForm>
+          <el-button @click="clickCancel" size="large">取 消</el-button>
+          <el-button type="primary" @click="clickSubmit()" size="large"> 确 定 </el-button>
+        </div>
+        <div style="display: flex" v-else>
+          <div style="width: 260px; border-right: 1px solid #eee; padding: 20px; max-height: calc(100vh - 100px - 72px - 60px); overflow-y: auto">
+            <ul v-infinite-scroll="load" class="infinite-list" style="overflow: auto">
+              <li v-for="(item, index) in sourceList.data" :key="item">
+                <div style="padding: 8px 0; color: #909399" v-if="judgeShow(sourceList.data, item, index)">
+                  <span>{{ dateFormat(item.date) }}</span>
+                  <span style="margin-left: 8px">{{ weekFormat(item.week) }}</span>
+                </div>
+                <div class="dailyPaper" @click="selectDailyPaper(item)">
+                  <el-icon :style="'transform: translateY(2px); color: ' + (dailyPaperId === item.id ? '#46a6ff;' : '#000;')"><User /></el-icon>
+                  <span :style="'margin-left: 8px; color: ' + (dailyPaperId === item.id ? '#46a6ff;' : '#000;')">{{ item.userName }}的日报</span>
+                </div>
+              </li>
+            </ul>
+          </div>
+          <div style="width: calc(100% - 260px); padding: 20px; max-height: calc(100vh - 100px - 72px - 60px); overflow-y: auto" v-if="dailyPaperId">
+            <div style="padding-bottom: 8px; position: relative">
+              <span style="font-size: 24px; font-weight: 700">{{ dailyPaperDetail.userName }}的日报</span>
+              <div style="position: absolute; right: 0; top: 7px; cursor: pointer">
+                <el-tooltip class="box-item" effect="light" placement="bottom-end">
+                  <template #content>
+                    <div style="padding: 8px 0; cursor: pointer" @click="clickShare(dailyPaperDetail)">分享这篇日报</div>
+                    <div
+                      style="padding: 8px 0; cursor: pointer"
+                      @click="clickLookOver(dailyPaperDetail)"
+                      v-if="dailyPaperDetail.createUser !== useUserStore().user.userId">
+                      查看所有日报
+                    </div>
+                  </template>
+                  <el-icon><MoreFilled /></el-icon>
+                </el-tooltip>
+              </div>
+            </div>
+            <div style="padding: 8px 0">
+              <span style="color: #909399" v-if="dailyPaperDetail.createTime">{{ dailyPaperDetail.createTime.substring(0, 10) }}</span>
+              <span style="color: #909399; margin-left: 16px">日报接收人</span>
+            </div>
+            <div style="padding: 8px 0">
+              <span style="font-size: 18px; font-weight: 700">今日完成工作:</span>
+            </div>
+            <div style="padding: 8px 0">
+              <div v-html="getStyle(dailyPaperDetail.completedWork)" v-if="dailyPaperDetail.completedWork"></div>
+              <div v-else>-</div>
+            </div>
+            <div style="padding: 8px 0">
+              <span style="font-size: 18px; font-weight: 700">未完成工作:</span>
+            </div>
+            <div style="padding: 8px 0">
+              <div v-html="getStyle(dailyPaperDetail.unfinishedWork)" v-if="dailyPaperDetail.unfinishedWork"></div>
+              <div v-else>-</div>
+            </div>
+            <div style="padding: 8px 0">
+              <span style="font-size: 18px; font-weight: 700">需协调工作:</span>
+            </div>
+            <div style="padding: 8px 0">
+              <div v-html="getStyle(dailyPaperDetail.coordinatedWork)" v-if="dailyPaperDetail.coordinatedWork"></div>
+              <div v-else>-</div>
+            </div>
+            <div style="padding: 8px 0">
+              <span style="font-size: 18px; font-weight: 700">图片:</span>
+            </div>
+            <div style="padding: 8px 0">
+              <div style="display: flex; flex-wrap: wrap" v-if="dailyPaperDetail.imgList && dailyPaperDetail.imgList.length > 0">
+                <div style="margin-right: 16px" v-for="item in dailyPaperDetail.imgList" :key="item.id">
+                  <el-image style="width: 100px; height: 100px; cursor: pointer" :src="item.fileUrl" fit="scale-down" @click="openFile(item)" />
+                </div>
+              </div>
+            </div>
+            <div style="padding: 8px 0">
+              <span style="color: #909399">{{ dailyPaperDetail.readCount }}人已读</span>
+            </div>
+            <div style="padding: 8px 0">
+              <span style="color: #909399">评分: </span>
+              <el-rate v-model="comment.data.star" :colors="colors" style="transform: translateY(3px)" />
+            </div>
+            <div style="padding: 8px 0; background-color: #eee">
+              <div style="display: flex; padding: 8px">
+                <el-input v-model="comment.data.text" placeholder="请输入评论内容" />
+                <el-button type="primary" style="margin-left: 16px" @click="commentSubmit()" size="large">发送</el-button>
+              </div>
+            </div>
+            <div style="padding: 8px 0" v-if="dailyPaperDetail.commentList && dailyPaperDetail.commentList.length > 0">
+              <div style="display: flex; margin-bottom: 16px" v-for="item in dailyPaperDetail.commentList" :key="item.id">
+                <div style="margin: 8px">
+                  <el-icon style="font-size: 32px"><User /></el-icon>
+                </div>
+                <div style="width: calc(100% - 48px)">
+                  <div style="padding: 4px 0; position: relative">
+                    <span>{{ item.userName }}</span>
+                    <div style="position: absolute; right: 0; top: 2px; cursor: pointer" @click="clickReply(item)">
+                      <el-icon style="transform: translateY(3px); font-size: 18px"><ChatDotRound /></el-icon>
+                      <span style="margin-left: 8px">回复</span>
+                    </div>
+                  </div>
+                  <div style="padding: 4px 0; color: #909399">{{ item.createTime }} 评价</div>
+                  <div style="padding: 4px 0">
+                    <el-rate v-model="item.star" :colors="colors" disabled />
+                  </div>
+                  <div style="padding: 4px 0; word-break: break-all; word-wrap: break-word">{{ item.text }}</div>
+                  <div style="display: flex; padding: 16px 0" v-if="reply.data.replyId === item.id">
+                    <el-input v-model="reply.data.text" placeholder="请输入回复内容" />
+                    <el-button type="primary" style="margin-left: 16px" @click="replySubmit()" size="large">回复</el-button>
+                  </div>
+                  <div style="padding: 8px 0" v-if="item.replyList && item.replyList.length > 0">
+                    <div v-for="reply in item.replyList" :key="reply.id">
+                      <div style="padding: 8px 0; color: #909399">{{ reply.userName }} {{ reply.createTime }} 回复</div>
+                      <div style="padding: 8px; background-color: #eee">{{ reply.text }}</div>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div style="width: calc(100% - 260px); padding: 20px; max-height: calc(100vh - 100px - 72px - 60px); overflow-y: auto" v-else></div>
+        </div>
+      </div>
+    </div>
+
+    <el-dialog title="分享日报" v-model="openShare" width="600">
+      <byForm :formConfig="formConfigShare" :formOption="formOption" v-model="formShare.data" :rules="rulesShare" ref="share">
+        <template #shareUser>
+          <div style="width: 100%">
+            <el-select v-model="formShare.data.toUserId" multiple class="m-2" placeholder="Select" size="large" style="width: 100%">
+              <el-option v-for="item in userList" :key="item.userId" :label="item.userName" :value="item.userId" />
+            </el-select>
+          </div>
+        </template>
+      </byForm>
+      <template #footer>
+        <el-button @click="openShare = false" size="large">取 消</el-button>
+        <el-button type="primary" @click="clickShareSubmit()" size="large"> 确 定 </el-button>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ElMessage } from "element-plus";
+import { ref, watch } from "vue";
+import moment from "moment";
+import useUserStore from "@/store/modules/user";
+import byForm from "@/components/byForm/index";
+
+const { proxy } = getCurrentInstance();
+const sourceList = ref({
+  data: [],
+  total: 0,
+  pagination: {
+    pageNum: 1,
+    pageSize: 10,
+    keyword: "",
+    senderId: "",
+    date: "",
+    type: "1",
+  },
+});
+const date = ref(moment().format("yyyy-MM-DD"));
+const calendar = ref();
+const menuDefault = ref("1");
+const dailyPaperId = ref("");
+const dailyPaperDetail = ref({});
+const newStatus = ref(false);
+const selectDate = (val) => {
+  calendar.value.selectDate(val);
+};
+const formOption = reactive({
+  inline: true,
+  labelWidth: 100,
+  itemWidth: 100,
+  rules: [],
+});
+const formData = reactive({
+  data: {
+    isVisibleToRecipient: 1,
+    imgList: [],
+    attachmentList: [],
+    dailyReportDetailsList: [],
+  },
+});
+const comment = reactive({
+  data: {
+    star: null,
+  },
+});
+const colors = ref(["#99A9BF", "#F7BA2A", "#FF9900"]);
+const reply = reactive({
+  data: {
+    replyId: "",
+    text: "",
+  },
+});
+const userList = ref([]);
+const imgList = ref([]);
+const attachmentList = ref([]);
+const dailyReportDetailsList = ref([]);
+const uploadData = ref({});
+const submit = ref(null);
+const formConfig = computed(() => {
+  return [
+    {
+      type: "input",
+      prop: "completedWork",
+      label: "今日完成工作",
+      itemType: "textarea",
+    },
+    {
+      type: "input",
+      prop: "unfinishedWork",
+      label: "未完成工作",
+      itemType: "textarea",
+    },
+    {
+      type: "input",
+      prop: "coordinatedWork",
+      label: "需协调工作",
+      itemType: "textarea",
+    },
+    {
+      type: "slot",
+      slotName: "productPic",
+      prop: "imgList",
+      label: "产品图片",
+    },
+    {
+      type: "slot",
+      slotName: "productFile",
+      prop: "attachmentList",
+      label: "附件",
+    },
+    {
+      type: "slot",
+      slotName: "recipient",
+      prop: "dailyReportDetailsList",
+      label: "发送到人",
+    },
+    {
+      type: "slot",
+      slotName: "more",
+      prop: "isVisibleToRecipient",
+      label: "更多",
+    },
+  ];
+});
+let rules = ref({
+  completedWork: [{ required: true, message: "请输入今日完成工作", trigger: "blur" }],
+  unfinishedWork: [{ required: true, message: "请输入未完成工作", trigger: "blur" }],
+  coordinatedWork: [{ required: true, message: "请输入需协调工作", trigger: "blur" }],
+});
+const formShare = reactive({
+  data: {
+    id: "",
+    toUserId: [],
+  },
+});
+const openShare = ref(false);
+const share = ref(null);
+const formConfigShare = computed(() => {
+  return [
+    {
+      type: "slot",
+      slotName: "shareUser",
+      prop: "toUserId",
+      label: "分享用户",
+    },
+  ];
+});
+let rulesShare = ref({
+  completedWork: [{ required: true, message: "请输入今日完成工作", trigger: "blur" }],
+});
+watch(
+  () => date.value,
+  (newValue) => {
+    sourceList.value.pagination.date = moment(newValue).format("yyyy-MM-DD");
+    sourceList.value.pagination.pageNum = 1;
+    sourceList.value.total = 0;
+    sourceList.value.data = [];
+    getList();
+  }
+);
+const handleSelectMenu = (index) => {
+  if (index == 1 || index == 2) {
+    sourceList.value.pagination.type = index;
+    sourceList.value.pagination.date = "";
+  } else {
+    sourceList.value.pagination.type = 2;
+    sourceList.value.pagination.date = moment().format("yyyy-MM-DD");
+  }
+  sourceList.value.pagination.pageNum = 1;
+  sourceList.value.pagination.senderId = "";
+  sourceList.value.total = 0;
+  sourceList.value.data = [];
+  getList();
+};
+const searchList = () => {
+  sourceList.value.pagination.pageNum = 1;
+  sourceList.value.pagination.senderId = "";
+  sourceList.value.total = 0;
+  sourceList.value.data = [];
+  getList();
+};
+const getList = () => {
+  newStatus.value = false;
+  proxy.post("/dailyReport/page", sourceList.value.pagination).then((res) => {
+    sourceList.value.data = sourceList.value.data.concat(res.rows);
+    sourceList.value.total = res.total;
+    if (
+      sourceList.value.data &&
+      sourceList.value.data.length > 0 &&
+      dailyPaperId.value !== sourceList.value.data[0].id &&
+      !sourceList.value.pagination.senderId
+    ) {
+      selectDailyPaper(sourceList.value.data[0]);
+    }
+    if (sourceList.value.total > sourceList.value.pagination.pageNum * sourceList.value.pagination.pageSize) {
+      load();
+    }
+  });
+};
+const newDaily = () => {
+  getUser();
+  formData.data = {
+    isVisibleToRecipient: 1,
+    imgList: [],
+    attachmentList: [],
+    dailyReportDetailsList: [],
+  };
+  dailyPaperId.value = "";
+  dailyPaperDetail.value = {};
+  newStatus.value = true;
+};
+const load = () => {
+  if (sourceList.value.total > sourceList.value.pagination.pageNum * sourceList.value.pagination.pageSize) {
+    sourceList.value.pagination.pageNum++;
+    getList();
+  }
+};
+const dateFormat = (dateStr) => {
+  var result = "";
+  if (dateStr != "") {
+    var contractDate = new Date(dateStr);
+    var contract_year = contractDate.getFullYear();
+    var contract_month = contractDate.getMonth() + 1;
+    var contract_day = contractDate.getDate();
+    result = contract_year + "年" + contract_month + "月" + contract_day + "日";
+  }
+  return result;
+};
+const weekFormat = (index) => {
+  let week = {
+    1: "周一",
+    2: "周二",
+    3: "周三",
+    4: "周四",
+    5: "周五",
+    6: "周六",
+    7: "周日",
+  };
+  return week[index];
+};
+const selectDailyPaper = (item) => {
+  dailyPaperDetail.value = {};
+  dailyPaperId.value = item.id;
+  proxy.post("/dailyReport/detail", { id: item.id }).then((res) => {
+    dailyPaperDetail.value = res;
+    proxy.post("/fileInfo/getList", { businessIdList: [item.id], fileType: 1 }).then((resPicture) => {
+      dailyPaperDetail.value.imgList = resPicture[item.id];
+    });
+    proxy.post("/fileInfo/getList", { businessIdList: [item.id], fileType: 2 }).then((resFile) => {
+      dailyPaperDetail.value.attachmentList = resFile[item.id];
+    });
+    proxy.post("/dailyReportComments/page", { pageNum: 1, pageSize: 999, dailyReportId: item.id }).then((res) => {
+      dailyPaperDetail.value.commentList = res.rows;
+    });
+  });
+};
+const judgeShow = (data, item, index) => {
+  let status = true;
+  if (index > 0 && data[index - 1].date === item.date) {
+    status = false;
+  }
+  return status;
+};
+const uploadPicture = async (file) => {
+  if (!["image/gif", "image/jpeg", "image/jpg", "image/png"].includes(file.type)) {
+    ElMessage("请上传格式为gif、jpeg、jpg、png的图片");
+    return false;
+  } else if (file.size / 1024 / 1024 > 3) {
+    ElMessage("单个图片不得超过3M");
+    return false;
+  } else {
+    const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
+    uploadData.value = res.uploadBody;
+    file.id = res.id;
+    file.fileName = res.fileName;
+  }
+  return true;
+};
+const uploadFile = async (file) => {
+  if (file.type !== "application/pdf") {
+    ElMessage("请上传格式为pdf的文件");
+    return false;
+  } else {
+    const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
+    uploadData.value = res.uploadBody;
+    file.id = res.id;
+    file.fileName = res.fileName;
+  }
+  return true;
+};
+const clickCancel = () => {
+  newStatus.value = false;
+  menuDefault.value = 1;
+  handleSelectMenu(1);
+};
+const clickSubmit = () => {
+  submit.value.handleSubmit(() => {
+    if (imgList.value && imgList.value.length > 0) {
+      formData.data.imgList = imgList.value.map((item) => {
+        return {
+          id: item.raw.id,
+          fileName: item.raw.fileName,
+        };
+      });
+    }
+    if (attachmentList.value && attachmentList.value.length > 0) {
+      formData.data.attachmentList = attachmentList.value.map((item) => {
+        return {
+          id: item.raw.id,
+          fileName: item.raw.fileName,
+        };
+      });
+    }
+    if (dailyReportDetailsList.value && dailyReportDetailsList.value.length > 0) {
+      formData.data.dailyReportDetailsList = dailyReportDetailsList.value.map((item) => {
+        return {
+          recipientId: item,
+        };
+      });
+      proxy.post("/dailyReport/add", formData.data).then(() => {
+        ElMessage({
+          message: "新建成功",
+          type: "success",
+        });
+        clickCancel();
+      });
+    } else {
+      ElMessage("请选择需要接收的人");
+    }
+  });
+};
+const getUser = () => {
+  proxy.get("/tenantUser/list", { pageNum: 1, pageSize: 999 }).then((res) => {
+    userList.value = res.rows.filter((item) => item.userId !== useUserStore().user.userId);
+  });
+};
+const getStyle = (val) => {
+  if (val) {
+    return val.replace(/\n|\r\n/g, "<br>");
+  } else {
+    return "";
+  }
+};
+const openFile = (file) => {
+  if (file && file.fileUrl) {
+    window.open(file.fileUrl, "_blank");
+  }
+};
+const commentSubmit = () => {
+  if (!comment.data.star) {
+    return ElMessage("请先进行评分");
+  }
+  if (!comment.data.text) {
+    return ElMessage("请输入评论内容");
+  }
+  proxy.post("/dailyReportComments/add", { ...comment.data, dailyReportId: dailyPaperId.value }).then(() => {
+    ElMessage({
+      message: "评论成功",
+      type: "success",
+    });
+    comment.data = {};
+    proxy.post("/dailyReportComments/page", { pageNum: 1, pageSize: 999, dailyReportId: dailyPaperId.value }).then((res) => {
+      dailyPaperDetail.value.commentList = res.rows;
+    });
+  });
+};
+const clickReply = (item) => {
+  reply.data.text = "";
+  reply.data.replyId = item.id;
+};
+const replySubmit = () => {
+  if (!reply.data.text) {
+    return ElMessage("请输入回复内容");
+  }
+  proxy.post("/dailyReportComments/add", { ...reply.data, dailyReportId: dailyPaperId.value }).then(() => {
+    ElMessage({
+      message: "回复成功",
+      type: "success",
+    });
+    reply.data.text = "";
+    reply.data.replyId = "";
+    proxy.post("/dailyReportComments/page", { pageNum: 1, pageSize: 999, dailyReportId: dailyPaperId.value }).then((res) => {
+      dailyPaperDetail.value.commentList = res.rows;
+    });
+  });
+};
+const clickShare = (detail) => {
+  formShare.data.id = detail.id;
+  formShare.data.toUserId = [];
+  openShare.value = true;
+};
+const clickShareSubmit = () => {
+  share.value.handleSubmit(() => {
+    proxy.post("/dailyReport/share", formShare.data).then(() => {
+      ElMessage({
+        message: "分享成功",
+        type: "success",
+      });
+      openShare.value = false;
+    });
+  });
+};
+const clickLookOver = (detail) => {
+  sourceList.value.pagination.pageNum = 1;
+  sourceList.value.pagination.senderId = detail.createUser;
+  sourceList.value.pagination.type = "2";
+  sourceList.value.total = 0;
+  sourceList.value.data = [];
+  getList();
+};
+getUser();
+getList();
+</script>
+
+<style lang="scss" scoped>
+.outer-layer {
+  margin: 20px 0;
+  display: flex;
+  justify-content: space-between;
+  .left {
+    background: #fff;
+    padding: 20px;
+    width: 360px;
+    max-height: calc(100vh - 100px - 72px - 60px);
+    overflow-y: auto;
+  }
+  .right {
+    background: #fff;
+    width: calc(100% - 380px);
+  }
+}
+.infinite-list {
+  height: calc(100vh - 100px - 72px - 60px - 40px);
+  padding: 0;
+  margin: 0;
+  list-style: none;
+  &::-webkit-scrollbar {
+    width: 0px;
+  }
+}
+.dailyPaper {
+  cursor: pointer;
+  width: 100%;
+  padding: 8px;
+}
+.dailyPaper:hover {
+  background-color: #eeeeee;
+}
+.infinite-list .infinite-list-item + .list-item {
+  margin-top: 10px;
+}
+::v-deep(.el-calendar-table .el-calendar-day) {
+  height: 40px;
+  display: grid;
+  place-items: center;
+}
+::v-deep(.el-calendar-table tr td:first-child) {
+  border-left: 0 !important;
+}
+::v-deep(.el-calendar-table tr:first-child td) {
+  border-top: 0 !important;
+}
+::v-deep(.el-calendar-table td) {
+  border-bottom: 0 !important;
+  border-right: 0 !important;
+}
+::v-deep(.el-calendar__body) {
+  padding: 12px 20px !important;
+  border-bottom: var(--el-calendar-header-border-bottom);
+}
+::v-deep(.el-calendar-table td.is-selected) {
+  border-radius: 50px;
+  background-color: #409eff;
+  color: #fff;
+}
+::v-deep(.el-menu) {
+  border-right: 0;
+}
+::v-deep(.el-menu-item) {
+  height: 40px;
+}
+</style>