xtf-calendar
组件说明
xtf-calendar 是日期选择和业务日历组件,适用于预约排期、日期筛选和门店排班。组件支持单选、多选、范围选择、禁选规则、状态标记、快捷区间、插槽定制和底部确认操作;range、multiple 的优先级高于 mode。
基础用法
1. 单日选择
使用 v-model 绑定单个 YYYY-MM-DD 日期:
<template><xtf-calendar v-model="value" @select="handleSelect" /></template>
<script>
export default {
data() {
return { value: '2026-06-09' }
},
methods: {
handleSelect(payload) {
console.log('选中日期:', payload.value)
}
}
}
</script>2. 范围选择与确认
范围模式的值为包含一个或两个日期的数组;显示确认按钮时可根据 completed 判断范围是否完整:
<template>
<xtf-calendar
v-model="rangeValue"
range
show-selection
show-clear
show-confirm
@confirm="handleConfirm"
@clear="handleClear"
/>
</template>
<script>
export default {
data() {
return { rangeValue: ['2026-06-03', '2026-06-07'] }
},
methods: {
handleConfirm(payload) {
console.log('确认范围:', payload.value, payload.completed)
},
handleClear(payload) {
console.log('已清空:', payload.value)
}
}
}
</script>3. 拖动范围选择
开启 dragSelect 后,在范围模式下按住日期并拖动到目标日期,即可实时预览并完成日期区间;轻触日期仍保持原有的两次点击选择行为。
<xtf-calendar
v-model="rangeValue"
range
drag-select
@drag-start="onDragStart"
@dragging="onDragging"
@drag-end="onDragEnd"
/>4. 月份与年份切换
默认点击标题中的年月即可展开月份面板,通过 - 和 + 切换年份,选择月份后回到日期网格。minDate 与 maxDate 会自动禁用不可进入的年份和月份。
<xtf-calendar current="2026-06-01" show-month-picker />5. 多选与禁选日期
多选模式可结合静态禁选、日期区间和动态禁选函数使用:
<template>
<xtf-calendar
v-model="dates"
multiple
:disabled-dates="disabledDates"
:disabled-date="disableWeekend"
@invalid="handleInvalid"
/>
</template>
<script>
export default {
data() {
return {
dates: ['2026-06-02'],
disabledDates: ['2026-06-10', { start: '2026-06-15', end: '2026-06-16' }]
}
},
methods: {
disableWeekend(day) {
return day.isWeekend
},
handleInvalid(payload) {
uni.showToast({ title: payload.day.value + ' 不可选', icon: 'none' })
}
}
}
</script>6. 快捷区间、状态和自定义日期格
快捷项的 value 可为日期值、日期数组或返回它们的函数;dateCell 插槽可重绘日期格:
<template>
<xtf-calendar
v-model="rangeValue"
range
:marks="marks"
:statuses="statuses"
:shortcuts="shortcuts"
@shortcut-click="handleShortcut"
>
<template #dateCell="{ day }">
<view style="display: flex; flex-direction: column; align-items: center">
<text>{{ day.date }}</text>
<text v-if="day.statusLabel" style="font-size: 18rpx">{{ day.statusLabel }}</text>
<text v-else-if="day.markLabel" style="font-size: 18rpx">{{ day.markLabel }}</text>
</view>
</template>
</xtf-calendar>
</template>
<script>
export default {
data() {
return {
rangeValue: [],
marks: [{ date: '2026-06-06', color: 'var(--xtf-color-success)', label: '促销' }],
statuses: [
{ date: '2026-06-08', type: 'blocked', label: '闭仓', color: 'var(--xtf-color-danger)' }
],
shortcuts: [{ key: 'campaign', label: '活动期', value: ['2026-06-06', '2026-06-08'] }]
}
},
methods: {
handleShortcut(payload) {
console.log('快捷区间:', payload.item.label, payload.value)
}
}
}
</script>全部属性
| 属性 | 类型 | 默认值 | 作用描述 | 适用范围 | | --- | --- | --- | --- | | value | String \| Array \| Date | '' | 选中值;单选输出字符串,多选和范围输出数组 | v-model / :value | | range | Boolean | false | 强制使用范围选择,优先级高于 multiple 和 mode | 日期区间 | | multiple | Boolean | false | 强制使用多选,优先级低于 range、高于 mode | 多日期选择 | | mode | String | 'single' | 选择模式:single / multiple / range;非法值回退单选 | 未使用 range、multiple 时 | | current | String | '' | 初始展示月份,传入日期字符串 | 定位首屏月份 | | minDate / maxDate | String | '' | 可选择日期的最小值、最大值,同时限制月份切换 | 日期范围限制 | | disabledDates | Array<String \| Date \| Array \| Object> | [] | 禁用单日、[start, end] 区间,或 { date }、{ start, end } | 静态禁选规则 | | disabledDate | (day: CalendarDay) => Boolean | null | 返回 true 时禁用该日期 | 动态禁选规则 | | disableBlocked | Boolean | false | statuses 项的 type 为 blocked 时是否禁止选择 | 业务关闭日期 | | marks | Array<CalendarMark> | [] | 日期圆点、标签和单元格样式标记 | 业务节点 | | statuses | Array<CalendarStatus> | [] | 日期状态文字及状态类型 | 满约、闭仓等状态 | | shortcuts | Array<CalendarShortcut> | [] | 顶部快捷日期或日期区间 | 快速筛选 | | weekendHighlight | Boolean | true | 是否高亮当前月的周末 | 周末视觉区分 | | firstDayOfWeek | String \| Number | 1 | 每周起始日,0 为周日,1 为周一;其他值按 0 至 6 归一化 | 本地化周视图 | | showHeader / showWeekdays | Boolean | true | 是否显示月份导航头、星期标题行 | 紧凑日历 | | showAdjacentMonths | Boolean | true | 是否显示相邻月日期;关闭后位置保留但内容隐藏 | 仅展示当前月 | | readonly | Boolean | false | 是否禁止选择和清空;月份仍可按边界切换 | 只读展示 | | allowSameDay | Boolean | true | 范围模式是否允许开始和结束日期相同 | 单日范围 | | maxRange | String \| Number | 0 | 范围模式最大天数,含起止日,0 不限制 | 限制预约周期 | | dragSelect | Boolean | false | 范围模式是否支持按住日期拖动选择 | 移动端连续日期选择 | | headerStyle / headerTitleStyle / headerActionStyle | String \| Object \| Array | '' | 标题栏容器、标题文字、导航和操作文字样式 | 标题区换肤 | | weekdayStyle | String \| Object \| Array \| Function | '' | 星期行每一项的样式;函数参数为 { label, index, weekDay },weekDay 为 0 至 6 | 星期文案换肤 | | showHeaderClear / headerClearText | Boolean / String | false / '' | 是否在标题栏显示清空操作及其文案 | 快速重选 | | showTodayButton / todayButtonText | Boolean / String | false / '' | 是否在标题栏显示本月跳转操作及其文案 | 快速回到当前月 | | showMonthSwitch / showModeLabel | Boolean | true / false | 是否显示上月下月导航、是否显示选择模式副标题 | 紧凑标题栏 | | showMonthPicker | Boolean | true | 是否允许点击月份标题展开年份和月份选择面板 | 月份年份切换 | | monthTitleFormat | String | 'YYYY年MM月' | 标题年月格式,支持 YYYY 和 MM 占位符 | 标题文案 | | showWatermark | Boolean | false | 是否显示底部背景水印 | 日历主题 | | watermarkText / watermarkStyle | String / String \| Object \| Array | '' / '' | 水印文案,默认当前面板年份;以及水印颜色、透明度等自由样式 | 品牌化背景 | | watermarkSize | String \| Number | '' | 水印字号,数字按 rpx 处理 | 水印尺寸 | | watermarkPosition | String | 'bottom-center' | 水印预设位置:center、top-left、top-right、bottom-left、bottom-right、bottom-center | 水印定位 | | showFooter | Boolean | false | 是否显示底部区域 | 使用底部插槽 | | showClear / showConfirm / showSelection | Boolean | false | 是否显示清空、确认、已选日期文案 | 明确提交型选择 | | clearText / confirmText | String | '' | 覆盖清空、确认按钮文案 | 自定义文案 | | rangeStartText / rangeEndText / sameDayText | String | '' | 覆盖范围起点、终点和同日标签文案 | 范围选择文案 | | activeColor / activeTextColor / rangeColor | String | '' | 选中背景、选中文字、范围背景色 | 局部主题定制 | | dateClass | String \| Object \| Array \| (day: CalendarDay) => String \| Object \| Array | '' | 日期单元格附加类名,可为按日期计算的函数 | 日期级样式 | | dateStyle | String \| Object \| Array \| (day: CalendarDay) => String \| Object \| Array | '' | 日期单元格附加样式,可为按日期计算的函数 | 日期级样式 | | selectedClass / rangeClass | String | '' | 已选项、范围中间项附加类名 | 选择态样式 | | rangeStartClass / rangeEndClass | String | '' | 范围起点、终点附加类名 | 区分范围端点 | | todayClass / disabledClass | String | '' | 今日、禁用日期附加类名 | 特殊日期样式 | | selectedStyle / rangeStyle | String \| Object \| Array | '' | 已选项、范围中间项附加样式 | 选择态样式 | | rangeStartStyle / rangeEndStyle | String \| Object \| Array | '' | 范围起点、终点附加样式 | 区分范围端点 | | todayStyle / disabledStyle | String \| Object \| Array | '' | 今日、禁用日期附加样式 | 特殊日期样式 | | customClass | String | '' | 根节点自定义类名 | 样式覆盖 | | customStyle | String \| Object \| Array | '' | 根节点自定义样式 | 动态样式覆盖 |
marks 数组每项支持的字段
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
date | String | Date | - | 对应日期 |
color / label | String | '' | 圆点颜色、日期下方文案 |
style / cellStyle | String | Object | '' | 日期单元格样式,cellStyle 优先 |
className | String | '' | 日期单元格类名 |
statuses 数组每项支持的字段
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
date | String | Date | - | 对应日期 |
type | String | '' | 状态类型;busy 和 blocked 有内置样式 |
label / color / textColor | String | '' | 状态文案、状态色、文案颜色 |
style / cellStyle / className | String | Object / String | '' | 日期单元格样式与类名 |
shortcuts 数组每项支持的字段
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
key | String | Number | 自动生成 | 快捷项唯一标识 |
label | String | '快捷日期' | 快捷项文案 |
value | String | Date | Array | () => String | Date | Array | '' | 选中值或返回选中值的函数 |
事件
| 事件名称 | 触发时机 | 回调参数 | 参数说明 |
|---|---|---|---|
input | 选中值变更时触发 | (value: String | Array) | v-model 的更新事件 |
update:value | 选中值变更时触发 | (value: String | Array) | Vue 3 风格的值更新事件 |
change | 选中值变更时触发 | (value, meta: { type: String, day?: CalendarDay, mode?: String, item?: Object }) | type 为 select、clear 或 shortcut |
select | 成功点击可选日期时触发 | (payload: { value, day: CalendarDay, mode: String }) | 更新后的值、所点日期和实际模式 |
confirm | 点击确认按钮或调用实例方法时触发 | (payload: { value, selectedValues: Array, mode: String, completed: Boolean }) | completed 表示范围是否已选完 |
clear | 点击清空按钮或调用实例方法时触发 | (payload: { value, mode: String }) | 清空后的值和实际模式 |
month-change | 点击月份导航并成功切换时触发 | (month: String) | 新月份第一天,格式为 YYYY-MM-01 |
month-picker-change | 月份面板打开、关闭或选择月份时触发 | ({ visible, year, month? }) | 当前面板状态及已选月份 |
shortcut-click | 点击并成功应用快捷项时触发 | (payload: { item: CalendarShortcut, value }) | 原快捷项和标准化后的选中值 |
range-start | 范围模式选择起点时触发 | (payload: { value: Array, day: CalendarDay }) | 仅含起点的值和日期对象 |
range-end | 范围模式选择终点时触发 | (payload: { value: Array, day: CalendarDay }) | 已按日期升序排列的范围和值末次点击日期 |
drag-start | 开始跨日期拖动时触发 | (payload: { value: Array, day: CalendarDay }) | 拖动起点 |
dragging | 拖动经过新日期时触发 | (payload: { value: Array, day: CalendarDay }) | 当前预览范围 |
drag-end | 拖动松手后触发 | (payload: { value: Array, day: CalendarDay }) | 最终拖动范围 |
invalid | 点击禁用日期时触发;只读或隐藏日期不触发 | (payload: { day: CalendarDay, mode: String }) | 被拒绝的日期和实际模式 |
事件使用示例
<template>
<xtf-calendar
v-model="value"
range
show-clear
show-confirm
@change="onChange"
@select="onSelect"
@confirm="onConfirm"
@clear="onClear"
@month-change="onMonth"
@shortcut-click="onShortcut"
@range-start="onStart"
@range-end="onEnd"
@invalid="onInvalid"
/>
</template>
<script>
export default {
data() {
return { value: [] }
},
methods: {
onChange(value, meta) {
console.log('change:', value, meta.type)
},
onSelect(payload) {
console.log('select:', payload.day.value)
},
onConfirm(payload) {
console.log('confirm:', payload.completed)
},
onClear(payload) {
console.log('clear:', payload.value)
},
onMonth(month) {
console.log('month-change:', month)
},
onShortcut(payload) {
console.log('shortcut-click:', payload.item.label)
},
onStart(payload) {
console.log('range-start:', payload.day.value)
},
onEnd(payload) {
console.log('range-end:', payload.value)
},
onInvalid(payload) {
console.log('invalid:', payload.day.value)
}
}
}
</script>方法
1. changeMonth(offset) — 切换展示月份
受 minDate 和 maxDate 限制;越界时不执行也不触发事件。
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
offset | Number | - | 负数切上月,正数切下月 |
返回值:void。
使用示例: this.$refs.calendar.changeMonth(1)。
2. clearSelection() — 清空当前选择
只读状态下不会执行。
返回值:void。
使用示例: this.$refs.calendar.clearSelection()。
3. confirmSelection() — 触发当前选择的确认事件
不要求选择完整范围,监听 confirm 的 completed 判断是否可提交。
返回值:void。
使用示例:
<template><xtf-calendar ref="calendar" v-model="value" range @confirm="handleConfirm" /></template>
<script>
export default {
data() {
return { value: ['2026-06-03', '2026-06-07'] }
},
mounted() {
this.$refs.calendar.confirmSelection()
},
methods: {
handleConfirm(payload) {
console.log('确认:', payload.value)
}
}
}
</script>插槽
| 插槽名称 | 作用域参数 | 说明 |
|---|---|---|
dateCell | { day: CalendarDay } | 覆盖单个日期格内容;day 含 value、date、isToday、isDisabled、isSelected、isInRange、statusLabel、markLabel 等状态 |
footer | { value, selectedValues, selectionText, clear, confirm } | 覆盖底部区域,可调用 clear()、confirm() 执行组件内置操作 |
主题说明
- 选中日期使用
--xtf-calendar-active-color和--xtf-calendar-active-text,可由activeColor、activeTextColor局部覆盖。 - 范围中间日期使用
--xtf-calendar-range-color,可由rangeColor局部覆盖。 - 容器使用
--xtf-card-bg、--xtf-card-border、--xtf-shadow-card;日期文字及状态使用--xtf-color-text、--xtf-color-text-secondary、--xtf-color-danger等主题变量。
如需全局调整主题,请在 xtf-config-provider 或主题配置中覆盖上述 CSS 变量。