vue/H5的日历组件可简单定制

news2025/3/18 10:47:57

在components创建riliZujian.vue

<template>
  <div class="max_box">
    <!-- 日历 文字 -->
    <div class="month">
      <div @click="lastMonth" class="monthText13">上月</div>
      <div class="monthText2">{{ year }}年{{ month }}月</div>
      <div class="monthText13" @click="nextMonth">下月</div>
    </div>

    <!-- 日历 周 -->
    <div class="week">
      <div v-for="weeks in weekArr" :key="weeks">
        {{ weeks }}
      </div>
    </div>

    <!-- 日历 日 -->
    <div class="day">
      <div
        :class="[{ checkday: !days.date }, { choose: days.flag }]"
        v-for="(days, index) in dayArr"
        :key="index"
      >
        {{ days.day }}
        <img src="./yidaka.png" class="dayImg" v-if="days.flag" />
      </div>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    already: {
      type: Array
    }
  },
  watch: {
    already: {
      handler (v) {
        // 监听getAlready方法 获得已打卡的样式
        this.getAlready()
      },
      immediate: true, // 第一次赋值时触发
      deep: true // 深度监听
    }
  },
  name: 'rili-zujian',
  data () {
    return {
      dayArr: [], // 当前月每日
      day: new Date().getDate(), // 当前日
      year: new Date().getFullYear(), // 当前年
      month: new Date().getMonth() + 1, // 当前月
      weekArr: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'], // 每周
      aheadDay: 0 // 前方空白天数数量
    }
  },
  mounted () {
    const that = this
    // 初始日期
    that.initDate()
  },
  methods: {
    // 渲染已经签到的日期
    getAlready () {
      for (const i in this.dayArr) {
        if (
          this.already.indexOf(new Date(this.dayArr[i].date).getTime()) === -1
        ) {
          this.$set(this.dayArr[i], 'flag', false)
        } else {
          this.$set(this.dayArr[i], 'flag', true)
        }
      }
    },

    // 初始化日期
    initDate () {
      const that = this
      that.dayArr = []
      // 当前月总天数
      const totalDay = new Date(that.year, that.month, 0).getDate()
      // 遍历总天数将日期逐个添加至数组
      for (let i = 1; i <= totalDay; i++) {
        // 得到需补充天数
        const value = new Date(that.year, that.month - 1, i).getDay()
        // 补充前面空白日期
        if (i === 1 && value !== 0) {
          that.addBefore(value)
          that.aheadDay = value
        }
        // 添加本月日期
        const obj = {}
        obj.date =
          that.year +
          '-' +
          that.formatNum(that.month) +
          '-' +
          that.formatNum(i)
        obj.day = i
        that.dayArr.push(obj)
        // 补充后面空白日期
        if (i === totalDay && value !== 6) that.addAfter(value)
      }
    },
    // 补充前面空白日期
    addBefore (value) {
      const that = this
      const totalDay = new Date(that.year, that.month - 1, 0).getDate()
      for (let i = 0; i < value; i++) {
        const obj = {}
        obj.date = ''
        obj.day = totalDay - (value - i) + 1
        that.dayArr.push(obj)
      }
    },
    // 补充后空白日期
    addAfter (value) {
      const that = this
      for (let i = 0; i < 6 - value; i++) {
        const obj = {}
        obj.date = ''
        obj.day = i + 1
        that.dayArr.push(obj)
      }
    },
    // 格式化日期位数
    formatNum (num) {
      return num < 10 ? '0' + num : num
    },
    // 上一个月
    lastMonth () {
      const that = this
      if (that.month === 1) {
        that.year -= 1
        that.month = 12
      } else {
        that.month -= 1
      }

      that.initDate()
      that.getAlready()
    },
    // 下一个月
    nextMonth () {
      const that = this
      if (that.month === 12) {
        that.year += 1
        that.month = 1
      } else {
        that.month += 1
      }
      that.initDate()
      that.getAlready()
    }
  }
}
</script>

<style lang="less" scoped>
// 最大的盒子
.max_box {
  width: 375px;
  box-sizing: border-box;
  background-color: none;
}
// 月周日的样式 flex布局
.month,
.week,
.day {
  width: 375px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
// 月的文字的样式
.month {
  height: 50px;
}
.monthText13 {
  width: 50px;
  height: 50px;
  line-height: 50px;
  text-align: center;
}
.monthText2 {
  width: 100px;
  height: 50px;
  line-height: 50px;
  text-align: center;
}
// 日 flex超出 的换行
.day {
  flex-wrap: wrap;
}
// 周和日 的div样式
.week > div,
.day > div {
  width: 32px;
  height: 32px;
  line-height: 32px;
  margin: 9px;
  text-align: center;
  position: relative;
}
// 本月之外的数字 改成白色 隐藏起来
.checkday {
  color: #f9f9f9;
}
// 已打卡 的日期 的样式
.choose {
  color: #ffffff;
  background: #b5443a;
  border-radius: 10px;
  position: relative;
}
.dayImg {
  width: 36px;
  height: 13px;
  position: absolute;
  top: -3px;
  left: 0;
}
</style>

在业务代码中引入 riliZujian 组件

<template>
  <!-- 打卡领取道具礼包 -->
  <div class="maxBox">
    <!-- 导航栏 只有返回键 -->
    <div
      class="title"
      :style="{ top: this.$route.query.statusBarHeight + 'px' }"
    >
      <img src="./climbersImg/title01.png" class="title01" @click="goBack" />
      <div class="title03"></div>
    </div>
    <!-- 打卡 背景图 -->
    <img src="./climbersImg/dakaMaxBg.png" class="dakabeijingtu" />

    <!-- 内容 -->
    <div class="content">
      <!-- 用户信息 -->
      <div class="content_top">
        <!-- 打卡 打卡规则 子绝父相 -->
        <img
          src="./climbersImg/dakaguize.png"
          class="dakaguize"
          @click="onDakaguize"
        />

        <img :src="userInfo.userHeadUrl" class="content_top_img" />
        <div class="content_top_text">
          <div class="content_top_text_1">
            <img
              src="./climbersImg/dakaText1.png"
              class="content_top_text_1_img"
            />
            <div class="content_top_text_1_number">
              {{ userInfo.signCount }}
            </div>
            <img
              src="./climbersImg/dakaText2.png"
              class="content_top_text_1_img"
            />
          </div>

          <div class="content_top_text_2">
            <div class="content_top_text_2_text">
              <span style="color: #b5443a">{{ userInfo.signCount }}</span
              >/{{ userInfo.amount }}元
            </div>
            <div class="content_top_text_2_text">
              满{{ userInfo.amount }}元自动发放到钱包
            </div>
          </div>
        </div>
      </div>
      <!-- 日历 -->
      
      <riliZujian :already="dakaData" @changeMonth="historysign" />
    </div>

    <!-- 弹出框 打卡规则 -->
    <van-popup v-model="showDakaguize" position="bottom" style="background: none;">
      <img src="./climbersImg/dakaguizeBig.png" class="guizetanchuang" />
    </van-popup>
  </div>
</template>

<script>
// getDakaSub,
import { getDakaUserInfo, getDakaRili } from '@/api/zhidou'
import riliZujian from '@/components/rilizujian.vue'

export default {
  name: 'climbers-dakalinglibao',
  data () {
    return {
      showDakaguize: false, // 弹出框 展示打卡规则的字段
      dakaData: [], // 打卡的日历的接收字段
      userInfo: {} // 用户的打卡和基本信息
    }
  },
  components: {
    riliZujian
  },
  mounted () {
    this.getUserInfo()
    this.historysign()
  },
  methods: {
    // 打开 打卡规则 的方法
    onDakaguize () {
      console.log(123)
      this.showDakaguize = true
    },
    // 获取当前用户的打卡基础信息
    getUserInfo () {
      getDakaUserInfo({ userId: this.$route.query.userId }).then((res) => {
        // console.log(res, 'res---')
        if (res.status === 200) {
          this.userInfo = res.data
        } else {
          this.$toast.fail(res.msg)
        }
      })
    },
    // 获取当前用户的打卡日历信息
    historysign () {
      getDakaRili({
        userId: 107,
        time: '2025-03-17 12:26:43'
      }).then((res) => {
        if (res.status === 200) {
          for (const i in res.data) {
            // 接口返回的每一项 如果为 true 则进来
            if (res.data[i]) {
              this.dakaData.push(new Date(i).getTime())
            }
          }
          // console.log(this.dakaData)
        } else {
          this.$toast.fail(res.msg)
        }
      })
    },
    // 返回到上级页面
    goBack () {
      this.$router.push({
        path: '/上级页面地址',
        query: {
          userId: this.$route.query.userId,
          statusBarHeight: this.$route.query.statusBarHeight
        }
      })
    }
  }
}
</script>

<style lang="less" scoped>
.maxBox {
  width: 375px;
  position: relative;
}
.title {
  width: 375px;
  height: 44px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  position: absolute;
  left: 0;

  .title01 {
    width: 28px;
    height: 28px;
    margin-left: 16px;
  }
  .title03 {
    width: 44px;
    height: 20px;
  }
}
.dakabeijingtu {
  width: 375px;
}
.content {
  width: 375px;
  // height: 500px;
  background-image: url(./climbersImg/dakaMinBg.png);
  background-size: 100% 100%;
  position: absolute;
  top: 250px;
  bottom: 0;

  .content_top {
    width: 343px;
    height: 94px;
    margin: 0 16px;
    border-bottom: 1px solid rgba(0, 0, 0, 0.1);
    display: flex;
    position: relative;

    .dakaguize {
      width: 34px;
      height: 96px;
      position: absolute;
      top: -23px;
      right: -18px;
    }
    .content_top_img {
      width: 56px;
      height: 56px;
      border-radius: 56px;
      margin: 21px 15px 0 18px;
    }
    .content_top_text {
      width: 254px;
      margin-top: 20px;

      .content_top_text_1 {
        width: 254px;
        height: 32px;
        display: flex;
        align-items: center;

        .content_top_text_1_img {
          height: 16px;
        }
        .content_top_text_1_number {
          height: 32px;
          line-height: 32px;
          font-size: 27px;
          font-weight: 700;
          color: #b5443a;
          margin: 0 5px;
        }
      }
      .content_top_text_2 {
        width: 254px;
        height: 20px;
        display: flex;

        .content_top_text_2_text {
          font-size: 14px;
          font-weight: 400;
          color: rgba(0, 0, 0, 0.5);
          margin-right: 8px;
        }
      }
    }
  }
}
.guizetanchuang {
  width: 375px;
}

::v-deep .van-calendar__header {
  background: rgba(255, 255, 255, 0.1);
}
::v-deep .van-calendar__body {
  background: rgba(255, 255, 255, 0.1);
}
::v-deep .van-calendar__header-title {
  display: none;
}
</style>

参考资料:签到组件、可签到和补签,统计签到天数和积分 - DCloud 插件市场

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

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

相关文章

STM32——独立看门狗(IWDG)

IWDG 简介 独立看门狗本质上是一个 定时器 &#xff0c;这个定时器有一个输出端&#xff0c;可以输出复位信号。该定时器是一个 12 位的递减计数器 &#xff0c;当计数器的值减到 0 的时候&#xff0c;就会产生一个复位信号。如果 在计 数没减到 0 之前&#xff0c;重置计…

C++11智能指针简述

一、实现原理 在智能指针对象中有一个裸指针&#xff0c;此指针存储的是动态创建对象的地址&#xff0c;用于生存期控制&#xff0c;能够确保智能指针对象离开所在作用域时&#xff0c;自动正确地销毁动态创建的对象&#xff0c;防止内存泄漏。 使用裸指针存在的问题&#xff…

Linux操作系统实验报告单(3)文本编辑器vi/vim

一、实验目的 掌握vi/vim编辑器的进入和退出方式了解vi/vim的三种模式熟练vi/vim的操作命令 二、实验内容 1.在家目录下新建一个名为“vitest_name”&#xff08;“name”为学生姓名拼音&#xff09;的目录。 ●创建用户目录命令&#xff1a;sudo mkdir /home/vitest_lw3613 …

Centos固定IP配置

虚拟机安装 安装vmware 网盘链接 安装centos7.5 网盘链接 安装教程自行查找 固定IP配置 对安装好的VMware进行网络配置&#xff0c;方便虚拟机连接网络&#xff0c;本次设置建议选择NAT模式&#xff0c;需要宿主机的Windows和虚拟机的Linux能够进行网络连接&#xff0c;…

二叉树算法题实战:从遍历到子树判断

目录 一、引言 二、判断两棵二叉树是否相同 思路 代码实现 注意点 三、二叉树的中序遍历 思路 代码实现 注意点 四、判断一棵树是否为另一棵树的子树 思路 代码实现 注意点 ​编辑 五、补充 一、引言 作者主页&#xff1a;共享家9527-CSDN博客 作者代码仓库&am…

学习threejs,使用MeshFaceMaterial面材质容器

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.MeshFaceMaterial 二…

Git 实战指南:本地客户端连接 Gitee 全流程

本文将以 Gitee(码云)、系统Windows 11 为例,详细介绍从本地仓库初始化到远程协作的全流程操作 目录 1. 前期准备1.1 注册与配置 Gitee1.2 下载、安装、配置客户端1.3 配置公钥到 Gitee2. 本地仓库操作(PowerShell/Git Bash)2.1 初始化本地仓库2.2 关联 Gitee 远程仓库3. …

Spring Cloud 中的服务注册与发现: Eureka详解

1. 背景 1.1 问题描述 我们如果通过 RestTamplate 进行远程调用时&#xff0c;URL 是写死的&#xff0c;例如&#xff1a; String url "http://127.0.0.1:9090/product/" orderInfo.getProductId(); 当机器更换或者新增机器时&#xff0c;这个 URL 就需要相应地变…

通过 SVG 使用 AI 生成理想图片:技术实现与实践指南

文章目录 1. SVG 与 AI 的结合&#xff1a;技术价值2. 技术原理&#xff1a;AI 如何生成 SVG&#xff1f;3. 实现步骤&#xff1a;从需求到图形3.1 定义需求3.2 使用 AI 生成 SVG3.3 验证与调整 4. 代码解析&#xff1a;实现科技感的关键4.1 渐变背景4.2 网格线条4.3 发光六边形…

【AI学习从零至壹】Pytorch神经⽹络

Pytorch神经⽹络 神经网络简介神经元激活函数 神经网络神经⽹络的⼯作过程前向传播(forward) 反向传播(backward)训练神经⽹络 Pytorch搭建并训练神经⽹络神经⽹络构建和训练过程数据预处理构建模型优化器&提取训练数据训练样本 神经网络简介 神经元 在深度学习中&#x…

设计模式-对象创建

对象创建 前言1. Factory Method1.1 模式介绍1.2 模式代码1.2.1 问题代码1.2.2 重构代码 1.3 模式类图1.4 要点总结 2. Abstract Factory2.1 模式介绍2.2 模式代码2.2.1 问题代码2.2.2 重构代码 2.3 模式类图2.4 要点总结 3. Prototype3.1 模式介绍3.2 模式代码3.3 模式类图3.4…

【AVRCP】Notification PDUs 深入解析与应用

目录 一、Notification PDUs 概述 二、GetPlayStatus:同步查询播放状态 2.1 命令功能与应用场景 2.2 请求格式(CT → TG) 2.3 响应格式(TG → CT) 2.4 注意事项 2.5 协议实现示例(伪代码) 三、RegisterNotification:异步事件订阅 3.1 命令概述 3.2 命令格式 …

MATLAB 控制系统设计与仿真 - 27

状态空间的标准型 传递函数和状态空间可以相互转换&#xff0c;接下来会举例如何有传递函数转成状态空间标准型。 对角标准型 当 G(s)可以写成&#xff1a; 即&#xff1a; 根据上图可知&#xff1a; 约当标准型 当 G(s)可以写成&#xff1a; 即&#xff1a; 根据上图…

linux 命令 cp

cp 是 Linux 中用于复制文件和目录的命令&#xff0c;基本功能是将源文件或目录复制到目标位置 基本语法 cp [选项] 源文件 目标文件 cp [选项] 源文件1 源文件2 ... 目标目录 常用选项 选项说明-i交互模式&#xff08;覆盖前询问确认&#xff09;-r 或 -R递归复制目录&#…

蓝桥杯高频考点——进制转换

进制转换 二进制转十进制代码演示 十六进制转十进制代码演示 十进制转K进制代码演示 任意进制之间的转换代码演示 二进制转十进制 代码演示 // 定义函数 calc&#xff0c;用于将字符转换为对应的数值 int calc(char c) {// 若字符 c 大于等于 9&#xff08;注&#xff1a;此处…

【算法百题】专题七_分治快排_专题八_分治归并

文章目录 前言分治快排题&#xff1a;043. [颜⾊分类&#xff08;medium&#xff09;](https://leetcode.cn/problems/sort-colors/description/)分析 044. [快速排序&#xff08;medium&#xff09;](https://leetcode.cn/problems/sort-an-array/description/)分析 045. [快速…

使用OBS进行webRTC推流参考

参考腾讯云官方文档&#xff1a; 云直播 OBS WebRTC 推流_腾讯云 说明非常详细&#xff0c;分为通过WHIP和OBS插件的形式进行推流。 注意&#xff1a;通过OBS插件的形式进行推流需要使用较低的版本&#xff0c;文档里有说明&#xff0c;需要仔细阅读。

(链表)面试题 02.07. 链表相交

给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保证 整个链式结构中不存在环。 注意&#xff0c;函数返回结果后&#xff…

Python----数据可视化(Pyecharts三:绘图二:涟漪散点图,K线图,漏斗图,雷达图,词云图,地图,柱状图折线图组合,时间线轮廓图)

1、涟漪特效散点图 from pyecharts.globals import SymbolType from pyecharts.charts import EffectScatter from pyecharts.faker import Faker from pyecharts import options as opts from pyecharts.globals import ThemeType # 绘制图表 es (EffectScatter(init_optsop…

IP风险度自检,互联网的安全“指南针”

IP地址就像我们的网络“身份证”&#xff0c;而IP风险度则是衡量这个“身份证”安全性的重要指标。它关乎着我们的隐私保护、账号安全以及网络体验&#xff0c;今天就让我们一起深入了解一下IP风险度。 什么是IP风险度 IP风险度是指一个IP地址可能暴露用户真实身份或被网络平台…