vue3 自己写一个月的日历

news2024/11/19 17:34:23

效果图
在这里插入图片描述
在这里插入图片描述
代码

<template>
  <div class="monthPage">
    <div class="calendar" v-loading="loading">
      <!-- 星期 -->
      <div class="weekBox">
        <div v-for="(item, index) in dayArr" :key="index" class="weekTit">{{ item.label }}</div>
      </div>

      <!-- 天数 -->
      <div class="itemBox" id="dateBox">
        <div
          v-for="(item, index) in dateArr"
          :key="index"
          :class="
                  (selectDay === item.No) & item.show
                     ? 'select dateItem hoverItem'
                     : item.show
                     ? 'dateItem hoverItem'
                     : 'dateItem'
               "
          @click="selectOneDay(item, index)"
        >
          <!-- 日历基本属性 -->
          <div class="oneLabel" :class="day == item.No ? ' active' : ''" v-show="item.show">
            <div class="dayDesc" style="color: #ff4d4f" v-show=" item.isWeekday==0">休息日</div>
            <div class="dayDesc">工作日</div>
            <div class="dateNo">{{ item.No }}</div>
          </div>

          <!-- 考勤标签 -->
          <div class="twoLabel">
            <!-- 异常 -->
            <div class="labelColor yichang" v-show="index===14">
              <i class="iconfont icon-icon_yichang"></i>
              <span>9</span>
            </div>
            <!-- 排班 -->
            <div class="labelColor banci" v-show="index===14">
              <i class="iconfont icon-icon_banci"></i>
              <span>6</span>
            </div>
            <!-- 加班 -->
            <div class="labelColor jiaban" v-show="index===14">
              <i class="iconfont icon-icon_jiaban"></i>
              <span>2</span>
            </div>
            <!-- 外出 -->
            <div class="labelColor waichu" v-show="index===14">
              <i class="iconfont icon-icon_waichu"></i>
              <span>5</span>
            </div>
            <!-- 休假 -->
            <div class="labelColor xiujia" v-show="index===14">
              <i class="iconfont icon-icon_xiujia"></i>
              <span>1</span>
            </div>
            <!-- 权限 -->
            <div class="labelColor quanxian" v-show="index===15">
              <i class="iconfont icon-icon_quanxian"></i>
              <span>3</span>
            </div>
            <!-- 节假日 -->
            <div class="labelColor festivalBg" v-show="index===15">
              <div>
                <i class="iconfont icon-icon_danju"></i>
              </div>
              <span>2</span>
            </div>
            <!-- 节假日加班 -->
            <div class="labelColor OvertimeBg" v-show="index===15">
              <div>
                <i class="iconfont icon-icon_danju"></i>
              </div>
              <span>2</span>
            </div>
          </div>

          <!-- 非本月日期 -->
          <div v-show="!item.show" class="oneLabel noData">
            <div class="dateNo">{{ item.No }}</div>
          </div>
        </div>

        <!-- 弹出窗 -->
        <div class="bubbleBox" v-show="bubbleFlag" :style="'top:' + top + 'px;left:' + left + 'px'">
          <div style="display:flex">
            <el-input v-model="dayFestival" placeholder="Please enter" style="margin-right:15px"></el-input>
            <el-button type="primary" @click="setFestival">确认</el-button>
          </div>

          <span class="spanleft" v-show="leftOrRight"></span>
          <span class="spanRight" v-show="!leftOrRight"></span>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { onMounted, reactive, toRefs, watch, getCurrentInstance } from 'vue'
export default {

  setup () {
    const { proxy } = getCurrentInstance()
    const data = reactive({
      year: '', // 年
      month: '', // 月
      day: '',
      lastDay: '',
      dayArr: [
        { label: "星期日", value: 7 },
        { label: "星期一", value: 1 },
        { label: "星期二", value: 2 },
        { label: "星期三", value: 3 },
        { label: "星期四", value: 4 },
        { label: "星期五", value: 5 },
        { label: "星期六", value: 6 }

      ],
      dateArr: [], // 当前月份的天数
      selectDay: null,
      prevMonth: '',
      bubbleFlag: false,
      top: 0,
      left: 0,
      leftOrRight: true,
      recordTypeList: [],
      organizationIdList: [],
      personIdList: [],
      loading: false,
      dayFestival: '',
      pageName: 'month',
      timeMove: ''
    })

    onMounted(() => {

      let date = new Date()
      data.year = date.getFullYear()
      data.month = date.getMonth()
      data.prevMonth = date.getMonth()
      data.day = addZero(date.getDate()) // 补零
      initDate()
    })
    const addZero = (date) => {
      return date.toString().padStart(2, '0')
    }

    const initDate = () => {
      data.dateArr = []
      //当前月存store
      let monthStr = 'el.datepicker.month' + (Number(data.month) + 1)
      let firstDay = new Date(data.year, data.month, 1).getDay() // 当月第一天星期几
      data.lastDay = new Date(data.year, data.month, 0).getDate() // 当月最后一天

      let prevLastDate = new Date(data.year, data.prevMonth, 0).getDate() // 上月的最后一天
      let monthNum = new Date(data.year, data.month + 1, -1).getDate() + 1 // 每月天数
      let dateStr = data.year + '-' + addZero(Number(data.month) + 1) + '-'

      for (let i = 1; i < monthNum + 1; i++) {
        let dateS = dateStr + addZero(i)
        data.dateArr.push({ No: i, show: true, punchDate: dateS }) // 遍历添加当前月份的每一天
      }

      for (let i = 0; i < firstDay; i++) {
        data.dateArr.unshift({
          No: prevLastDate - i,
          show: false,
          punchDate: '',
        }) //向前填充日期
      }

      let len = 8 - (data.dateArr.length % 7)
      for (let i = 1; i < len; i++) {
        data.dateArr.push({ No: i, show: false, punchDate: '' }) // 向后填充日期
      }
    }

    //获取日历数据
    const getList = async () => {

    }
    //选择日期
    const selectOneDay = (row, index) => {
      let e = window.event
      let dateBox = document.getElementById('dateBox')
      let ww = dateBox.clientWidth / 7
      let indexk = (Number(index) + 1) % 7
      let dateBoxWidth = dateBox.clientWidth - 123 //宽度修正值
      let dateBoxHeight = dateBox.clientHeight + 10 //高度修正值
      let scrollTop = dateBox.scrollTop
      if (!row.show) {
        data.bubbleFlag = false
        return
      }
      if (row.No === data.selectDay) {
        data.bubbleFlag = false
        data.selectDay = null
      } else {
        data.bubbleFlag = true
        data.selectDay = row.No
        let topNum = e.layerY + scrollTop
        let letNum = ww * indexk
        if (letNum === 0) {
          data.leftOrRight = false
          letNum = ww * 6 - 120
        } else {
          data.leftOrRight = true
        }
        data.left = letNum
        data.top = topNum > dateBoxHeight ? dateBoxHeight : topNum
      }
      data.dayFestival = row.customFestivalName || row.festivalName
    }
    // 标签弹窗
    const handleDialog = (id, type, punchDate) => {

    }
    // 自定义假日
    const setFestival = async (row) => {
      data.bubbleFlag = false
    }
    //监听前进后退
    watch(
      () => data.timeMove,
      (val) => {
        if (data.pageName === 'month') {
          if (val === 'next') {
            data.prevMonth++
            if (Number(data.month) + 1 > 11) {
              data.month = 0
              data.year = Number(data.year) + 1
            } else {
              data.month = Number(data.month) + 1
            }
            initDate()
          } else if (val === 'prev') {
            data.prevMonth--
            if (Number(data.month) - 1 < 0) {
              data.month = 11
              data.year = data.year - 1
            } else {
              data.month = Number(data.month) - 1
            }
            initDate()
          } else if (val === 'today') {
            let date = new Date()
            data.year = date.getFullYear()
            data.month = date.getMonth()
            data.prevMonth = date.getMonth()
            data.day = addZero(date.getDate()) // 补零
            initDate()
          }
        }
      },
      {
        deep: true,
      }
    )



    return {
      ...toRefs(data), // 将 data 返回出去,就可以直接使用 data 里面的属性
      selectOneDay,
      getList,
      handleDialog,
      initDate,
      setFestival,
    }
  },
}
</script>

<style scoped lang="scss">
.monthPage {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  height: 79vh;
  .calendar {
    width: 100%;
    height: 100%;
    background-color: #fff;
    // display: flex;
    // flex-wrap: wrap;
    .weekBox {
      height: 36px;
      display: flex;
      // flex-wrap: wrap;
      .weekTit {
        width: calc(100% / 7);
        padding-left: 10px;
        font-size: 14px;
        color: #606266;
        height: 36px;
        line-height: 36px;
        border-bottom: 1px solid #e4e7ed;
      }
    }

    .itemBox {
      height: 100%;
      overflow: scroll;
      display: flex;
      flex-wrap: wrap;
      padding-bottom: 30px;
      position: relative;
      .dateItem {
        width: calc(100% / 7);
        height: 158px;
        padding-left: 10px;
        color: #404040;
        font-size: 20px;
        box-sizing: border-box;
        border: 2px solid transparent;
        border-bottom: 2px solid #e4e7ed;
        padding: 9px;
        // position: relative;
        cursor: pointer;
        display: flex;
        justify-content: space-between;
        flex-direction: column;
        .oneLabel {
          width: 100%;
          height: 24px;
          margin-bottom: 4px;
          .dayDesc {
            color: #888888;
            font-size: 12px;
            float: right;
            text-align: right;
          }
          .dateNo {
            font-size: 20px;
            color: #404040;
          }
        }
        .active {
          .dayDesc {
            color: #1890ff;
          }
          .dateNo {
            color: #1890ff;
          }
        }
        .noData {
          float: left;
          width: calc(100% + 18px);
          height: 158px;
          margin: -9px;
          background: #f6f8f9;
          padding: 9px;
          cursor: default;
        }
        .twoLabel {
          width: calc(100% - 18px);
          display: flex;
          justify-content: space-between;
          flex-wrap: wrap-reverse;
          align-content: flex-end;
          height: auto;
          .labelColor {
            width: 49%;
            height: 24px;
            line-height: 24px;
            padding: 0 7px;
            font-size: 12px;
            margin-bottom: 4px;
            border-radius: 2px;
            padding: 0 7px;
            display: flex;
            justify-content: space-between;
            color: #ffffff;
            position: relative;
            z-index: 10;
            cursor: pointer;
          }
        }
      }
      .hoverItem {
        &:hover {
          border: 2px solid #1890ff;
        }
      }
      .select {
        background-color: #1890ff;
        border-color: #1890ff;
        .oneLabel {
          .dayDesc {
            color: #fff;
          }
          .dateNo {
            color: #fff;
          }
        }
      }
      .bubbleBox {
        padding: 7px 17px;
        box-sizing: border-box;
        position: absolute;
        top: 0;
        left: 0;
        background: #fff;
        z-index: 22;
        border-radius: 3px;
        box-shadow: 0px 0px 6px 0px rgba(0, 0, 0, 0.34);
        p {
          width: 100%;
          height: 26px;
          line-height: 26px;
          cursor: pointer;
          &:hover {
            color: #1890ff;
          }
        }
        .spanleft {
          position: absolute;
          left: -10px;
          top: 10px;
          width: 0;
          height: 0;
          border: 5px solid transparent;
          border-right: 5px solid #fff;
          z-index: 2;
        }
        .spanRight {
          position: absolute;
          right: -10px;
          top: 10px;
          width: 0;
          height: 0;
          border: 5px solid transparent;
          border-left: 5px solid #fff;
          z-index: 2;
        }
      }
    }
  }
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1298174.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

5G+AI开花结果,助力智慧安检落地

“请带包的乘客过机安检&#xff01;”&#xff0c;深圳地铁、腾讯共同打造的5GAI智慧安检辅助系统亮相福田枢纽站&#xff0c;进一步解放了人力&#xff0c;提高安检效率&#xff0c;为交通安全保驾护航&#xff0c;让智慧出行成为现实。 传统的安检设备均为人工肉眼辨识&…

【Vue+Python】—— 基于Vue与Python的图书管理系统

文章目录 &#x1f356; 前言&#x1f3b6;一、项目描述✨二、项目展示&#x1f3c6;三、撒花 &#x1f356; 前言 【VuePython】—— 基于Vue与Python的图书管理系统 &#x1f3b6;一、项目描述 描述&#xff1a; 本项目为《基于Vue与Python的图书管理系统》&#xff0c;项目…

Java第21章网络通信

网络程序设计基础 网络程序设计编写的是与其他计算机进行通信的程序。Java 已经将网络程序所需要的元素封 装成不同的类&#xff0c;用户只要创建这些类的对象&#xff0c;使用相应的方法&#xff0c;即使不具备有关的网络支持&#xff0c;也可 以编写出高质量的网络…

手把手带你创建HAL版本MDK工程模板

手把手带你创建HAL版本MDK工程模板 如何快速开发 STM32 项目&#xff1f;我们总不能每次开发一个项目就搭建一次工程&#xff0c;这样效率太低了。 通常我们会使用一个模板工程&#xff0c;需要开发新项目的时候拿出来添加一些对应的模块及业务代码&#xff0c;一个项目就开发…

BearPi Std 板从入门到放弃 - 先天篇(1)(阶段 : 智慧城市 - 智慧路灯)

简介 对前面几篇整合, 做个小小汇总试验, 使用BearPi E53_SC1扩展板主芯片: STM32L431RCT6串口: Usart1扩展板与主板连接: I2C : I2C1 (光照强度传感器&#xff1a;BH1750)LED: PB9步骤 创建项目 参考 BearPi Std 板从入门到放弃 - 引气入体篇&#xff08;1&#xff09;(由零创…

LabelImg的使用及注意事项

LabelImg是一款开源的图像标注工具&#xff0c;它主要用于标注目标检测、语义分割和图像分类等深度学习中需要的数据集。通过使用LabelImg&#xff0c;用户可以快速、准确地为图片中的目标添加标注信息&#xff0c;从而建立数据集。 使用步骤&#xff1a; 下载LabelImg&#x…

word中,文本框如何跨页?

我们经常使用word编辑一些文档&#xff0c;文档中往往会有一些比较大的文本框&#xff0c;需要跨多页&#xff0c;我们可以使用本文章中的方法&#xff0c;将文本框连接在一起&#xff0c;是的内容自动跨页。 在文字中插入两个文本框如下图&#xff1a; 将内容放到第一个文本框…

基于SpringBoot的大学活动平台

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 随着互联网技术的不断…

Kotlin:内置函数let、also、with、run、apply

前言 在Kotlin中&#xff0c;有一些用于扩展 & 方便开发者编码的内置函数&#xff0c;能大大提高开发者的开发效率。今天&#xff0c;我将主要讲解的是&#xff1a; let函数also函数with函数run函数apply函数 基础知识&#xff1a;接口回调中Lambda使用 在Kotlin中可使用…

Carla自动驾驶仿真六:pygame多个车辆摄像头画面拼接

此文章主要介绍carla前后左右摄像头画面拼接到pygame上 文章目录 前言一、要点分析二、完整代码三、拼接效果四、总结 前言 1、使用carla做仿真测试或者开发时&#xff0c;如果能够将车辆周边的画面拼接并渲染&#xff0c;可以直观地查看周围地环境&#xff0c;便于调试。本文…

SpringBoot 自动装配原理详解

什么是 SpringBoot 自动装配&#xff1f; 我们现在提到自动装配的时候&#xff0c;一般会和 Spring Boot 联系在一起。但是&#xff0c;实际上 Spring Framework 早就实现了这个功能。Spring Boot 只是在其基础上&#xff0c;通过 SPI 的方式&#xff0c;做了进一步优化。 Spr…

社区分享|简米Ping++基于MeterSphere开展异地测试协作

上海简米网络科技有限公司&#xff08;以下简称为“简米”&#xff09;是国内开放银行服务商&#xff0c;高新技术企业&#xff0c;中国支付清算协会会员单位。自2014年成立至今&#xff0c;简米长年聚焦金融科技领域&#xff0c;通过与银行、清算组织等金融机构合作&#xff0…

python爬虫学习-批量爬取图片

python爬虫学习-批量爬取图片 爬虫步骤爬取前十页图片到本地根据页码获取网络源码使用xpath解析网页解析网页并下载图片主函数如下 爬取的网站为站长素材&#xff08;仅做学习使用&#xff09; 爬取的目标网站为 https://sc.chinaz.com/tupian/qinglvtupian.html如果爬取多页&…

【ArcGIS Pro微课1000例】0051:创建数据最小几何边界范围(点、线、面数据均可)

本实例为专栏系统文章:创建点数据最小几何边界(范围),配套案例数据,持续同步更新! 文章目录 一、工具介绍二、实战演练三、注意事项一、工具介绍 创建包含若干面的要素类,用以表示封闭单个输入要素或成组的输入要素指定的最小边界几何。 工具界面及参数如下所示: 核心…

Python Reflex框架全攻略:手把手教你打造个性化全栈应用!

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com Reflex框架是一款专注于全栈开发的现代 JavaScript 框架&#xff0c;它强调响应式编程和简化复杂性&#xff0c;为开发者提供了构建动态且高效的全栈应用的工具。 Reflex框架是为了解决传统全栈开发中的一些挑战…

在python中安装库,会有conda安装,也会有pip安装,conda与pip的区别是什么?

文章目录 一、Conda是什么&#xff1f;二、pip是什么&#xff1f;三、pip与conda的区别&#xff1a;总结 一、Conda是什么&#xff1f; Conda是一个开源的包管理系统&#xff0c;它是Anaconda公司为Python和其他编程语言开发的。它主要用于数据科学和机器学习领域&#xff0c;…

通过Mock玩转Golang单元测试!

1.单元测试中的困难 如果项目中没有单元测试&#xff0c;对于刚刚开始或者说是规模还小的项目来说&#xff0c;效率可能还不错。但是一旦项目变得复杂起来&#xff0c;每次新增功能或对旧功能的改动都要重新手动测试一遍所有场景&#xff0c;费时费力&#xff0c;而且还有可能…

windows的cmd/PowerShell修改中文字符编码

1.简介 由于编程的时候经常会用到不同的编码&#xff0c;但是由于cmd/bat脚本和命令行默认的编码不一致&#xff0c;就导致了输出的中文乱码&#xff0c;使用chcp命令可以修改当前命令行的编码方式 2.查看与修改 2.1.查看 chcp 常用编码编号 65001&#xff1a;UTF-8936&am…

Python-pdf工具自制(合并、拆分、删除)

pdf工具&#xff0c;之前写的合并工具有点麻烦&#xff0c;使用PyQt5库重写合并拆分和删除指定页面的程序 实现如图&#xff1a; 代码&#xff1a; import sysimport osfrom PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget, QFileDia…

P10 Linux进程编程 fork创建子进程

目录 前言 01 fork()创建子进程 示例 1使用 fork()创建子进程。 02 fork创建新进程时发生了什么事&#xff1f; 2.1 父、子进程中对应的文件描述符指向了相同的文件表 前言 &#x1f3ac; 个人主页&#xff1a;ChenPi &#x1f43b;推荐专栏1: 《Linux C应用编程&#xf…