当前位置: 首页 > news >正文

uni-app 全能日历组件,支持农历、酒店预订、打卡签到、价格日历多种场景

一、uView Pro 的 Calendar 组件


uni-app 开发中,日期选择是一个高频需求场景。无论是酒店预订的入住离店时间选择、电商平台的商品预约、还是日常应用的
打卡签到,一个功能完善、体验优秀的日历组件都是必不可少的。

uView Pro 作为 uni-app 生态中备受关注的
Vue3 组件库,其Calendar 日历组件经过了多个版本的迭代优化,从最初的基础日期选择,逐步演进为支持
农历显示、打卡签到、节假日标记、自定义价格日历
等丰富功能的综合型组件。

本文将深入解析 uView Pro Calendar 组件的核心特性、实现原理以及实际应用场景,帮助你快速掌握这个强大的日期选择利器。

二、组件概览:功能特性总览

uView Pro 的 Calendar 日历组件具有以下核心特性:

基础功能

  • ✅ 支持单日期选择和日期范围选择两种模式
  • ✅ 底部弹窗和页面嵌入两种展示方式
  • ✅ 年月切换导航,支持自定义年份范围
  • ✅ 日期范围限制,防止选择无效日期

进阶功能

  • ✅ 农历显示支持,自动计算农历日期
  • ✅ 打卡签到模式,支持已打卡/未打卡状态展示
  • ✅ 节假日和加班日标记,显示"休"/"班"标识
  • ✅ 内置中国传统节日,支持自定义节日配置
  • ✅ 自定义日期内容插槽,适用于价格日历等场景

交互优化

  • ✅ 默认选中今天,支持指定默认日期
  • ✅ 只读模式,禁止日期选择
  • ✅ 选中效果可配置,适应不同视觉需求

三、基础使用:快速上手

3.1 单日期选择模式

单日期选择是最常用的场景,比如选择生日、预约日期等。

<template> <view> <u-calendar v-model="show" mode="date" @change="onChange"></u-calendar> <u-button @click="show = true">选择日期</u-button> </view> </template> <script setup lang="ts"> import { ref } from 'vue' import type { CalendarChangeDate } from 'uview-pro/types/global' const show = ref(false) function onChange(e: CalendarChangeDate) { console.log('选择的日期:', e.result) console.log('星期:', e.week) console.log('是否今天:', e.isToday) } </script>

回调参数说明:

属性说明类型
year选择的年份number
month选择的月份number
day选择的日期number
result格式化的日期字符串,如 "2024-06-15"string
week星期文字,如 "星期六"string
isToday是否选择了今天boolean

3.2 日期范围选择模式

范围选择适用于酒店预订、行程规划等需要起止时间的场景。

<template> <u-calendar v-model="show" mode="range" start-text="入住" end-text="离店" @change="onRangeChange" > <template #tooltip> <view class="tip">请选择入住和离店时间</view> </template> </u-calendar> </template> <script setup lang="ts"> import { ref } from 'vue' import type { CalendarChangeRange } from 'uview-pro/types/global' const show = ref(false) function onRangeChange(e: CalendarChangeRange) { console.log('入住日期:', e.startDate) console.log('离店日期:', e.endDate) console.log('共', e.endDay - e.startDay + 1, '晚') } </script>

范围模式回调参数:

属性说明
startDate / endDate起始/结束日期字符串
startYear / endYear起始/结束年份
startMonth / endMonth起始/结束月份
startDay / endDay起始/结束日期
startWeek / endWeek起始/结束星期

四、进阶功能详解

4.1 农历显示

Calendar 组件内置了农历计算功能,开启后会自动显示农历日期。

<u-calendar v-model="show" mode="date" :show-lunar="true" @change="onLunarChange" ></u-calendar>

开启农历后,回调参数会增加lunar对象:

{ day: 15, month: 6, result: "2024-06-15", lunar: { dayCn: '初十', // 农历日 monthCn: '五月', // 农历月 year: 2024, // 农历年 weekCn: "星期六" // 农历星期 } }

农历显示会自动处理闰月、大小月等复杂逻辑,无需开发者关心底层实现。

4.2 页面嵌入模式

除了弹窗模式,组件还支持直接嵌入页面显示,适用于需要常驻展示日历的场景。

<template> <view class="calendar-page"> <u-calendar :is-page="true" mode="date" @change="onChange" ></u-calendar> </view> </template>

页面模式的特点:

  • 不显示弹窗和确定按钮
  • 选择日期后自动触发change事件
  • 支持所有其他功能(农历、打卡、节假日等)

4.3 打卡签到模式

打卡签到日历也是近期咨询我比较多的功能,Calendar 组件专门为此设计了打卡模式。

<template> <u-calendar :is-page="true" :checkin-mode="true" :checked-dates="checkedDates" :today-checked="todayChecked" ></u-calendar> </template> <script setup> import { ref } from 'vue' // 已打卡日期列表 const checkedDates = ref([ '2024-01-01', '2024-01-02', '2024-01-03', '2024-01-05' ]) // 今日打卡状态(优先级高于自动判断) const todayChecked = ref(true) </script>

打卡模式的显示规则:

  1. 今日已打卡:绿色圆形背景,显示白色对勾
  2. 其他已打卡日期:橙色圆形背景,显示日期
  3. 未打卡日期checkin-mode为 true 时):灰色圆形背景

颜色自定义:

属性说明默认值
checked-bg-color已打卡日期背景色橙色(warning)
today-checked-bg-color今日已打卡背景色绿色(success)
unchecked-bg-color未打卡日期背景色灰色(light)

4.4 节假日与加班日标记

组件支持显示节假日和加班日标记,方便用户了解日期属性。

<template> <u-calendar :is-page="true" :holidays="holidays" :workdays="workdays" ></u-calendar> </template> <script setup> import { ref } from 'vue' // 节假日(元旦假期) const holidays = ref(['2024-01-01', '2024-01-02']) // 加班日(调休上班) const workdays = ref(['2024-01-06', '2024-01-07']) </script>

显示效果:

  • 节假日:日期右上角显示红色"休"字
  • 加班日:日期右上角显示蓝色"班"字
  • 选中状态下,"休"/"班"字变为白色

4.5 节日显示

组件内置了中国传统节日,同时支持自定义节日配置。

内置节日(show-festival为 true 时自动显示):

  • 元旦(1月1日)
  • 情人节(2月14日)
  • 妇女节(3月8日)
  • 植树节(3月12日)
  • 愚人节(4月1日)
  • 劳动节(5月1日)
  • 青年节(5月4日)
  • 儿童节(6月1日)
  • 建党节(7月1日)
  • 建军节(8月1日)
  • 教师节(9月10日)
  • 国庆节(10月1日)
  • 光棍节(11月11日)
  • 圣诞节(12月25日)

自定义节日:

<template> <u-calendar :is-page="true" :show-festival="true" :festivals="customFestivals" ></u-calendar> </template> <script setup> import { ref } from 'vue' const customFestivals = ref({ // 每年固定节日(MM-DD 格式) '04-04': '清明节', '05-05': '端午节', '08-15': '中秋节', // 特定年份节日(YYYY-MM-DD 格式)- 优先级更高 '2025-04-04': '清明节(2025)', // 覆盖内置节日(传入空字符串不显示) '02-14': '', }) </script>

优先级规则:

  1. 特定年份格式(YYYY-MM-DD)优先级最高
  2. 每年固定格式(MM-DD)次之
  3. 内置节日优先级最低

4.6 自定义日期内容:价格日历

通过date插槽,可以完全自定义每个日期的显示内容,常用于电商价格日历场景。

<template> <u-calendar :is-page="true" mode="date" :use-date-slot="true" > <template #date="{ date }"> <text :class="getPriceClass(date)"> {{ getPriceText(date) }} </text> </template> </u-calendar> </template> <script setup> import { ref } from 'vue' // 价格数据 const priceMap = ref({ '2024-01-01': 299, '2024-01-02': 399, '2024-01-03': 359, // ... }) function getPriceText(date) { if (date.isToday) return '今天' const price = priceMap.value[date.date] return price ? `¥${price}` : '' } function getPriceClass(date) { if (date.isSelected) return 'price-selected' if (date.isToday) return 'price-today' return 'price-normal' } </script> <style scoped> .price-today { color: #19be6b; font-weight: bold; } .price-normal { color: #909399; font-size: 22rpx; } .price-selected { color: #ffffff; } </style>

插槽作用域参数:

属性说明类型
date.year年份number
date.month月份number
date.day日期number
date.date完整日期字符串string
date.week星期文字string
date.isToday是否今天boolean
date.isHoliday是否节假日boolean
date.isWorkday是否加班日boolean
date.isChecked是否已打卡boolean
date.isSelected是否选中boolean
date.lunar农历信息object

五、核心实现原理浅析

5.1 日历渲染逻辑

Calendar 组件的日历渲染基于以下核心算法:

// 获取某月天数 function getMonthDay(year: number, month: number) { return new Date(year, month, 0).getDate() } // 获取某月第一天星期几(0-6) function getWeekday(year: number, month: number) { let date = new Date(`${year}/${month}/01 00:00:00`) return date.getDay() }

渲染流程:

  1. 计算当月第一天是星期几,生成前置空白格子
  2. 计算当月总天数,生成日期格子
  3. 根据选中状态计算每个格子的样式
  4. 如果有农历,调用农历转换库计算农历日期

5.2 农历计算

组件使用了独立的农历计算工具Calendar.solar2lunar,将公历日期转换为农历:

function getLunar(year: any, month: any, day: any) { const val = Calendar.solar2lunar(year, month, day) return { dayCn: val.IDayCn, // 农历日(初十、廿三等) monthCn: val.IMonthCn, // 农历月(正月、五月等) weekCn: val.ncWeek, // 农历星期 day: val.lDay, // 农历日数字 month: val.lMonth, // 农历月数字 year: val.lYear // 农历年 } }

5.3 范围选择逻辑

范围选择采用两次点击确定起止时间的交互方式:

function dateClick(dayIdx: number) { const d = dayIdx + 1 const date = `${year.value}-${month.value}-${d}` if (props.mode == 'range') { // 判断是设置开始日期还是结束日期 const compare = new Date(date).getTime() < new Date(startDate.value).getTime() if (isStart.value || compare) { // 设置开始日期 startDate.value = date isStart.value = false } else { // 设置结束日期 endDate.value = date isStart.value = true // 触发回调 if (props.isPage) btnFix(true) } } }

六、实际应用场景

6.1 酒店预订日历

<u-calendar v-model="show" mode="range" start-text="入住" end-text="离店" :min-date="minDate" :max-date="maxDate" @change="onDateChange" > <template #tooltip> <view class="hotel-tip"> <text>请选择入住和离店日期</text> <text class="sub">入住时间14:00后,离店时间12:00前</text> </view> </template> </u-calendar>

6.2 健身打卡应用

<u-calendar :is-page="true" :checkin-mode="true" :checked-dates="monthCheckins" :today-checked="todayChecked" :show-lunar="true" @change="onCheckin" ></u-calendar>

6.3 航班价格日历

<u-calendar :is-page="true" mode="date" :use-date-slot="true" :default-select-today="false" :is-active-current="false" > <template #date="{ date }"> <view class="flight-price"> <text class="day">{{ date.day }}</text> <text class="price" v-if="getPrice(date.date)"> ¥{{ getPrice(date.date) }} </text> </view> </template> </u-calendar>

6.4 日程管理应用

<u-calendar :is-page="true" :show-festival="true" :festivals="customFestivals" :holidays="holidays" :workdays="workdays" :default-date="selectedDate" @change="onSelectDate" ></u-calendar>

七、API 完整参考

Props 属性

参数说明类型默认值
v-model控制弹窗显示/隐藏booleanfalse
mode选择模式:date 单选 / range 范围stringdate
is-page是否在页面中直接显示booleanfalse
show-lunar是否显示农历booleanfalse
readonly是否只读booleanfalse
default-date默认选中日期(单选模式)string-
start-date默认开始日期(范围模式)string-
end-date默认结束日期(范围模式)string-
default-select-today默认选中今天booleantrue
min-date最小可选日期string1950-01-01
max-date最大可选日期string今天
min-year最小可选年份number/string1950
max-year最大可选年份number/string2050
change-year是否显示年份切换按钮booleantrue
change-month是否显示月份切换按钮booleantrue
active-bg-color选中日期背景色string主题色
active-color选中日期文字颜色string白色
range-bg-color范围内日期背景色string主题色浅
range-color范围内日期文字颜色string主题色
start-text开始日期提示文字string开始
end-text结束日期提示文字string结束
tool-tip顶部提示文字string选择日期
closeable是否显示关闭图标booleantrue
mask-close-able点击遮罩是否关闭booleantrue
safe-area-inset-bottom底部安全区适配booleanfalse
border-radius弹窗圆角number/string20
z-index弹窗层级number/string10075
is-active-current选中日期是否高亮booleantrue
checkin-mode是否启用打卡模式booleanfalse
checked-dates已打卡日期列表array[]
today-checked今日是否已打卡booleanfalse
checked-bg-color已打卡背景色string橙色
today-checked-bg-color今日已打卡背景色string绿色
unchecked-bg-color未打卡背景色string灰色
holidays节假日列表array[]
workdays加班日列表array[]
holiday-color节假日文字颜色string红色
workday-color加班日文字颜色string蓝色
show-festival是否显示内置节日booleanfalse
festivals自定义节日配置object{}
festival-color节日文字颜色string主题色
use-date-slot是否启用日期插槽booleanfalse

Events 事件

事件名说明回调参数
change日期选择完成时触发CalendarChangeDate / CalendarChangeRange

Slots 插槽

名称说明
tooltip自定义顶部提示内容
date自定义日期内容(作用域插槽)

八、总结

uView Pro 的 Calendar 日历组件是一个功能全面、设计精良的日期选择解决方案。从基础的单日期选择到复杂的打卡签到、价格日历,这些都能轻松应对。

使用建议:

  1. 选择合适的展示模式:弹窗模式适合临时选择,页面模式适合常驻展示
  2. 合理利用默认选中:通过default-datedefault-select-today提升用户体验
  3. 注意日期格式:所有日期参数统一使用YYYY-MM-DD格式
  4. 自定义插槽优先级:使用date插槽时会覆盖农历、节日等默认显示
  5. 打卡模式注意today-checked优先级高于checkedDates的自动判断

功能使用建议:

  • 如需农历功能,请确保使用支持该功能的版本
  • 如需打卡签到、节假日、自定义插槽等高级功能,请使用最新版本

如果你正在开发 uni-app 项目,需要一个功能强大、易于定制的日历组件,uView Pro 的 Calendar 值得一试,快来体验一下。

http://www.jsqmd.com/news/774973/

相关文章:

  • 5分钟快速上手!Calibre豆瓣插件终极安装指南,轻松获取中文图书元数据
  • AI编程助手集成Codex CLI:MCP协议实现智能代码分析与本地模型部署
  • AI原生OPC项目路演实录分享
  • 怎么配置中转站,稳定的爽用gpt 5.5,附cc switch + codex 配置教程
  • 第六篇:Redo Log与Binlog——崩溃恢复的底层保障
  • AutoJS Pro9.3最新文档详解与入门教程
  • Arm架构通用定时器原理与应用全解析
  • Flutter for OpenHarmony 学习路线实战:从环境搭建到跨端数据持久化全流程解析
  • MYSQL的视图
  • Termi AI:基于Electron的智能桌面开发伴侣,集成Vite预览与AI编程助手
  • 第七篇:慢查询分析与SQL优化实战
  • copilot学生认证按键无法点击
  • golang如何实现桌面应用热更新_golang桌面应用热更新实现攻略
  • MyBatis 高频八股文:从 Mapper 到缓存,一篇搞懂常见面试题
  • Python配置管理实战:从环境变量到类型安全,详解Tanuki单文件库设计
  • #81_闲谈语言的分类
  • linux kernel CONFIG_KCMP解析
  • YOLOv11室内地面塑料袋目标检测数据集-30张-Plastic-Bag-1
  • 微信福音:2345清理王微信专清功能介绍
  • 告别GPIO模拟!用STM32的FSMC高效驱动TFT屏,刷图速度提升实测
  • 吃透C++ STL map/set:从入门到实战,新手也能轻松上手
  • 车载诊断架构---解答售后关于Service 19 06疑问带来的反思
  • 3203黄大年茶思屋榜文保姆级全落地解法「32期3题」量子启发式算法|大规模百万节点图平衡最小分割优化
  • 用Python+PuLP搞定钢管运输优化:手把手复现2000年数模国赛B题
  • 大语言模型如何构建创业者认知代理:从特征工程到RAG应用
  • dotnet-skills:让AI助手掌握现代.NET开发最佳实践
  • 欧拉回路(一笔画)
  • “灵语星火”第二阶段团队记录(一)
  • 如何在华为HarmonyOS设备上部署microG服务:解决签名验证的完整技术指南
  • 开源情报实战指南:从工具到体系的OSINT方法论与自动化实践