vue3 手写日历组件

news2024/9/30 7:15:01

找了很久vue3的element样式一直没办法修改实现。只能手写日历了。借鉴了一些大佬的代码

调用:

再要使用的地方引入

import calendarelement from './calendarelement.vue'  //日历组件
 <div >     
        <calendarelement />  //日历
    </div>

效果:

<template>
  <div class="plan-zone">
    <div class="btn-group">
      <div class="left-btn">
        <el-button-group>
          <el-button @click="prevMonth" type="primary">上一个月</el-button>          
          <el-button type="primary" @click="goToCurrentDay">回到今天</el-button>
          <el-button @click="nextMonth" type="primary">下一个月</el-button>
        </el-button-group>
      </div>
      <div class="right-btn">
        <button class="new">长箱</button>
        <button class="ing">短箱</button>
        <button class="finish">双箱</button>
      </div>
    </div>
    <table class="parent-table">
      <thead>
        <th>周一</th>
        <th>周二</th>
        <th>周三</th>
        <th>周四</th>
        <th>周五</th>
        <th>周六</th>
        <th>周日</th>
      </thead>
      <tbody>
        <tr v-for="(week, windex) in weeks" :key="windex">
          <td v-for="(day, dindex) in week" :class="{ highlight: isToday(day.date) }" :key="dindex">
            <div class="content"
                 :class="{
                   faded: !isCurrentMonth(day.date),
                   hovered: isHovered(day.date),
                   selected: isSelected(day.date)
                 }"
                 @mouseenter="hoveredDay = day.date"
                 @mouseleave="hoveredDay = null"
                 @click="selectDay(day.date)"
            >
              <div class="top-day">{{ day.date.getDate() }}日  </div>
              <div class="middle-event">
                <div>
                  <span style="color: #409eef;">长箱</span>:<span>123</span>
                </div>
                </div>
              <div class="bottom-event">
                <div>
                  <span style="color: #ff974a;">短箱</span>:<span>123</span>
                </div>
              </div>
              <div class="bottom-event">
                <div>
                  <span style="color: #3dd599;">双箱</span>:<span>123</span>
                </div>
              </div>
          </div> 
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>



<script setup>
import { ref, computed } from 'vue';

const current = ref(new Date());
const today = ref(new Date());

const getCurDate = () => {
  const date = new Date();
  const year = date.getFullYear();
  let month = date.getMonth() + 1;
  if (month < 10) {
    month = "0" + month;
  }
  return `${year}-${month}`;
};

const isToday = (date) => {
  const todayDate = new Date();
  return (
    date.getDate() === todayDate.getDate() &&
    date.getMonth() === todayDate.getMonth() &&
    date.getFullYear() === todayDate.getFullYear()
  );
};

const goToCurrentDay = () => {
  current.value = new Date(today.value);
};

const isCurrentMonth = (date) => {
  return date.getMonth() === current.value.getMonth();
};

const prevMonth = () => {
  current.value.setMonth(current.value.getMonth() - 1);
  current.value = new Date(current.value);
};

const nextMonth = () => {
  current.value.setMonth(current.value.getMonth() + 1);
  current.value = new Date(current.value);
};


const hoveredDay = ref(null);
const selectedDay = ref(null);

const isHovered = (date) => hoveredDay.value && hoveredDay.value.getTime() === date.getTime();
const isSelected = (date) => selectedDay.value && selectedDay.value.getTime() === date.getTime();
const selectDay = (date) => selectedDay.value = date;


const getMonthData = (year, month) => {
  const weeks = [];
  const firstDay = new Date(year, month - 1, 1);
  const lastDayOfCurrentMonth = new Date(year, month, 0);
  const lastDayOfPrevMonth = new Date(year, month - 1, 0);

  let startDayOfWeek = firstDay.getDay() === 0 ? 7 : firstDay.getDay();
  let dayCount = 1;
  let prevMonthDayCount = lastDayOfPrevMonth.getDate() - startDayOfWeek + 2;

  for (let i = 0; i < 6; i++) {
    const week = [];
    for (let j = 0; j < 7; j++) {
      if (i === 0 && j < startDayOfWeek - 1) {
        week.push({ date: new Date(year, month - 2, prevMonthDayCount++) });
      } else if (dayCount > lastDayOfCurrentMonth.getDate()) {
        week.push({
          date: new Date(year, month, dayCount++ - lastDayOfCurrentMonth.getDate()),
        });
      } else {
        week.push({ date: new Date(year, month - 1, dayCount++) });
      }
    }
    weeks.push(week);
  }
  return weeks;
};

const weeks = computed(() => getMonthData(current.value.getFullYear(), current.value.getMonth() + 1));

</script>

 <style lang="scss" scoped>
.faded {
  opacity: 0.3;
}
.highlight {
  background: rgba(255, 220, 40, 0.15);
}
.plan-zone {
  margin-top: 10px;
  .btn-group {
    display: flex;
    justify-content: space-between;
    .right-btn {
      button.new {
        background-color: #fff;
        border: 1px solid #fff;
        color: #409eef;
        position: relative;
        &::before {
          content: "";
          width: 8px;
          height: 8px;
          border-radius: 50%;
          position: absolute;
          top: 7px;
          left: -3px;
          background-color: #409eef;
        }
      }
      button.ing {
        background-color: #fff;
        border: 1px solid #fff;
        color: #ff974a;
        position: relative;
        &::before {
          content: "";
          width: 8px;
          height: 8px;
          border-radius: 50%;
          position: absolute;
          top: 7px;
          left: -3px;
          background-color: #ff974a;
        }
      }
      button.finish {
        background-color: #fff;
        border: 1px solid #fff;
        color: #3dd599;
        position: relative;
        &::before {
          content: "";
          width: 8px;
          height: 8px;
          border-radius: 50%;
          position: absolute;
          top: 7px;
          left: -3px;
          background-color: #3dd599;
        }
      }
    }
  }
}
.parent-table {
  border-collapse: collapse;
  table-layout: fixed;
  width: 100%;
  margin-top: 20px;
  th,
  td {
    width: 14.4%;
    border: 1px solid #ddd;
  }
  td {
    padding: 2px 3px;
    .content {
      position: relative;
      min-height: 80px;
      transition: background-color 0.3s ease;
    }
    vertical-align: top;
    .top-day {
      text-align: right;
      font-size: 16px;
    }
  }
}
.table-date {
  display: flex;
  > div {
    flex: 1;
  }
}
.hovered {
  background-color: rgba(64, 56, 180, 0.1);
}
.selected {
  background-color: rgba(70, 168, 40, 0.2);
}
</style>

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

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

相关文章

押金原路退回系统在医院中应用,一键操作秒到账 押金+身份证+电子押金单

一、医院押金管理必要性 保障医疗服务的连续性&#xff1a;患者缴纳押金能够确保在治疗过程中&#xff0c;医院有足够的资金来提供必要的医疗服务、药品和设备&#xff0c;不会因为费用问题而中断治疗。例如&#xff0c;在紧急手术或需要持续使用昂贵药物的情况下&#xff0c;…

【Vue3】组件通信之$attrs

【Vue3】组件通信之$attrs 背景简介开发环境开发步骤及源码总结 背景 随着年龄的增长&#xff0c;很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来&#xff0c;技术出身的人总是很难放下一些执念&#xff0c;遂将这些知识整理成文&#xff0c;以纪念曾经努力学习奋斗的…

开发在线客服系统新的宣传推广站【微客客服】

打造一个软件宣传官网&#xff0c;这事儿可不简单。咱们得先搞清楚&#xff0c;这个网站要给谁看&#xff0c;要传达啥信息&#xff0c;需要哪些功能。 我们网站是宣传【在线客服系统】的&#xff0c;所以需要把主要功能展示清楚 在线网址&#xff1a;https://weikefu.com.cn 然…

Python面试宝典第27题:全排列

题目 给定一个不含重复数字的数组nums&#xff0c;返回其所有可能的全排列 。备注&#xff1a;可以按任意顺序返回答案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]] 示例 2&#xff1a; 输…

Qt之Gui

组件依赖关系 应用 #mermaid-svg-GADicZtZJRVVUeiF {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GADicZtZJRVVUeiF .error-icon{fill:#552222;}#mermaid-svg-GADicZtZJRVVUeiF .error-text{fill:#552222;stroke:#…

【Spark计算引擎----第三篇(RDD)---《深入理解 RDD:依赖、Spark 流程、Shuffle 与缓存》】

前言&#xff1a; &#x1f49e;&#x1f49e;大家好&#xff0c;我是书生♡&#xff0c;本阶段和大家一起分享和探索大数据技术Spark—RDD&#xff0c;本篇文章主要讲述了&#xff1a;RDD的依赖、Spark 流程、Shuffle 与缓存等等。欢迎大家一起探索讨论&#xff01;&#xff0…

【Gold菜鸟】Linux知识回忆(8)——进程和计划任务

前言 这部分让我们来继续了解Linux中进程和计划任务的相关知识吧~ 相关技术交流欢迎添加VX: wenjinworkon 目录 进程和内存管理 什么是进程 进程结构 进程相关概念 物理地址空间和虚拟地址空间 用户和内核空间 进程使用内存问题 进程状态 内存淘汰数据机制&#xff1a;…

数学建模评价类—Topsis法

目录 文章目录 前言 切记&#xff1a;以下内容仅用于参考理解&#xff0c;不可用于数模竞赛&#xff01;&#xff01;&#xff01; 一、Topsis的基本原理 二、Topsis的建模过程 1.判断矩阵是否需要正向化 2.原始矩阵正向化 3.矩阵标准化 4.计算距离&#xff0c;给出得…

Can Large Language Models Provide Feedback to Students? A Case Study on ChatGPT

文章目录 题目摘要相关工作方法结果讨论意义 题目 大型语言模型能为学生提供反馈吗&#xff1f;ChatGPT 案例研究 论文地址&#xff1a;https://ieeexplore.ieee.org/abstract/document/10260740 摘要 摘要——教育反馈已被广泛认为是提高学生学习能力的有效方法。然而&#x…

Python | Leetcode Python题解之第322题零钱兑换

题目&#xff1a; 题解&#xff1a; class Solution:def coinChange(self, coins: List[int], amount: int) -> int:dp [float(inf)] * (amount 1)dp[0] 0for coin in coins:for x in range(coin, amount 1):dp[x] min(dp[x], dp[x - coin] 1)return dp[amount] if d…

Python的if语句及其运用

一、条件测试 每条if语句的核心都是一个值为True或False的表达式&#xff0c;这种表达式称为条件测试。如果测试的条件满足if语句则为True&#xff0c;接着执行if里的语句&#xff1b;如果测试的条件不满足if语句则为False&#xff0c;则不执行if里的语句。 1.1、检查是否相等…

C++ | Leetcode C++题解之第322题零钱兑换

题目&#xff1a; 题解&#xff1a; class Solution { public:int coinChange(vector<int>& coins, int amount) {int Max amount 1;vector<int> dp(amount 1, Max);dp[0] 0;for (int i 1; i < amount; i) {for (int j 0; j < (int)coins.size();…

二叉树(真题)

1.用非递归遍历求二叉树结点个数【计学2020】 算法思想:用先序非递归遍历 当前指针不为空或栈不为空进行循环&#xff1b; 当前指针不为空访问当前结点&#xff0c;当前节点入栈&#xff0c;进入左子树 当前指针为空&#xff0c;栈顶元素出栈&#xff08;回溯&#xff09;&…

【kickstart+pxe批量安装linux系统】

目录 一、实验环境准备二、安装kickstart1、kickstart自动安装脚本的制作 三、安装web服务器&#xff0c;提供网络源四、安装dhcp五、安装syslinux&#xff0c;tftp-server六、虚拟机中新建新主机 一、实验环境准备 1、rhel7主机 2、开启主机图形 init 5 开图形 3、配置网络可…

ESP8266 烧录,待坑

ets Jan 8 2013,rst cause:1, boot mode:(7,0)waiting for host 空芯片&#xff0c;未加SPI FLASH 显示 下载模式(IO15 10k下拉 &#xff0c; IO0下拉 &#xff08;直接GND),IO2上拉&#xff08;文档上说是有内部上拉的&#xff0c;先上拉&#xff09;&#xff09; &#xff…

jdbc(mysql)

1.概述 jdbc&#xff1a;java database connection&#xff08;java与数据库连接&#xff09; java可以连接不同数据库&#xff0c;不同数据库连接细节不同&#xff0c;具体细节都由数据库自己实现 由java设计出一系列连接数据库的接口规范&#xff0c;然后由不同的数据库开发…

C语言程序设计26

《C程序设计教程&#xff08;第四版&#xff09;——谭浩强》 习题2.3 上机运行下面的程序&#xff0c;分析输出结果 代码 //《C程序设计教程&#xff08;第四版&#xff09;——谭浩强》 //习题2.3 上机运行下面的程序&#xff0c;分析输出结果#include <stdio.h> int …

【MYSQL】MYSQL逻辑架构

mysql逻辑架构分为3层 mysql逻辑架构分为3层 1). 连接层&#xff1a;主要完成一些类似连接处理&#xff0c;授权认证及相关的安全方案。 2). 服务层&#xff1a;在 MySQL据库系统处理底层数据之前的所有工作都是在这一层完成的&#xff0c;包括权限判断&#xff0c;SQL接口&…

GD 32 IIC通信协议

前言&#xff1a; ... 通信方式 通信方式分为串行通信和并行通信。常见的串口就是串行通信的方式 常用的串行通信接口 常用的串行通信方式有USART,IIC,USB,CAN总线 同步与异步 同步通信&#xff1a;IIC是同步通信&#xff0c;有两个线一个是时钟信号线&#xff0c;一个数数据…

rocketMq-5.2.0双主双从搭建

最近在研究rocketmq5.x的运行机制&#xff0c;研究到高可用章节&#xff0c;看到rocketMq采用了主从机制实现高可用&#xff0c;将broker分成了master和slave。为了更好的理解主从源码&#xff0c;我觉着需要先搭建一个主从的集群&#xff0c;先了解主从集群是怎么使用的。 这篇…