uni-calendar组件不支持直接实现考勤签到日历,需通过custom-item插槽自定义渲染签到状态、禁用日期及交互逻辑,并注意跨平台兼容性与日期格式处理。

uni-app里用 uni-calendar 组件前先看清楚它到底支持什么
uni-app 官方的 uni-calendar 组件不能直接做考勤签到日历——它只负责渲染日期格子、高亮选中/范围,不提供「标记签到状态」「自定义日格样式」等能力。很多开发者拉进来就改 lunar、show-week,结果发现签到红点、已签/未签图标、灰色禁用日期全得自己补。
真实使用场景是:你已有后端返回的签到记录数组(比如 ['2024-06-01', '2024-06-05']),需要在日历上标出哪些日子打过卡、哪些能点、哪些不可操作。
-
uni-calendar的date属性只控制“当前显示月份”,不是“可选日期” -
insert模式下无法响应点击;必须用range或single模式 + 手动拦截@change - 它不暴露日格 DOM,没法用 class 去加签到小红点——得靠
custom-item插槽(H5/小程序支持,App端部分版本不支持)
手动实现签到日历:用 uni-calendar + 自定义插槽 + 状态映射
核心思路是放弃依赖组件内置逻辑,把它当纯 UI 容器,所有状态由你控制。关键在 custom-item 插槽里根据当前日期动态渲染内容。
假设你从接口拿到 this.signList = ['2024-06-01', '2024-06-05', '2024-06-10'],且规则是:已签=红色圆点,今日=蓝色边框,不可签=禁用态(灰色+无点击)。
- 在
<uni-calendar></uni-calendar>内写<template></template>,item是当前格子的日期对象(含date、isCurrentMonth等) - 把
item.date格式化为YYYY-MM-DD字符串,查是否在signList里 - 用
v-if控制显示:已签用<view class="dot dot-signed"></view>,未签但可点用<view class="dot dot-unsign"></view> - 注意:App端(尤其是 iOS)可能不触发
@tap,建议统一用@click并加catchtouchmove防止穿透
日期格式和时区坑:后端返回的字符串别直接塞给 uni-calendar
常见错误是后端返回 "2024-06-01T00:00:00Z" 或 "2024/06/01",直接传给 date 属性会导致 H5 显示错月、小程序报 Invalid Date。
-
uni-calendar的date必须是标准 ISO 格式字符串(YYYY-MM-DD),且不含时间部分 - 用
new Date(str).toISOString().split('T')[0]安全转换,别信str.slice(0,10)—— 遇到"2024/06/01"就崩 - 如果后端按用户时区返回日期(比如北京时间 6.1 00:00 对应 UTC 5.31 16:00),用
new Date().toLocaleDateString('zh-CN')取本地日期再格式化,比依赖服务端更稳 - App端对
Date构造函数兼容性差,推荐用uni.$u.time.format(new Date(), 'yyyy-mm-dd')(若引入了 uView)或手写正则提取
性能与体验细节:滚动卡顿、重复请求、点击反馈缺失
考勤日历常要加载近 3 个月数据,但 uni-calendar 默认一次性渲染整月 42 个格子,加上每个格子都查数组、格式化、条件判断,低端安卓机滑动会掉帧。
- 避免在
custom-item插槽里调用复杂方法——把signMap = new Set(signList)提前算好,查状态用signMap.has(formattedDate) - 不要每次
@change都重新请求全量签到数据;按需加载:切换月份时,只请求该月 + 上月最后 3 天 + 下月前 3 天(覆盖跨月视图) - 点击签到没反馈?
uni.showToast在某些小程序平台(如 QQ 小程序)会被拦截,改用uni.showLoading({title:'...',mask:true})+setTimeout(uni.hideLoading, 800) - 禁用日期的视觉反馈必须明显:除了置灰,建议加
opacity: 0.4和pointer-events: none(H5 有效,小程序需用disabled属性或透明遮罩)
最麻烦的其实是跨平台差异:App 端 custom-item 渲染慢、iOS 小程序 touch 事件延迟、微信小程序真机上 isCurrentMonth 判断偶尔翻车——这些没法靠一个配置解决,得留好钩子,按 uni.getSystemInfoSync().platform 分路径处理。










