Skip to content

xtf-calendar

组件说明

xtf-calendar 是日期选择和业务日历组件,适用于预约排期、日期筛选和门店排班。组件支持单选、多选、范围选择、禁选规则、状态标记、快捷区间、插槽定制和底部确认操作;rangemultiple 的优先级高于 mode


基础用法

1. 单日选择

使用 v-model 绑定单个 YYYY-MM-DD 日期:

vue
<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 判断范围是否完整:

vue
<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 后,在范围模式下按住日期并拖动到目标日期,即可实时预览并完成日期区间;轻触日期仍保持原有的两次点击选择行为。

vue
<xtf-calendar
  v-model="rangeValue"
  range
  drag-select
  @drag-start="onDragStart"
  @dragging="onDragging"
  @drag-end="onDragEnd"
/>

4. 月份与年份切换

默认点击标题中的年月即可展开月份面板,通过 -+ 切换年份,选择月份后回到日期网格。minDatemaxDate 会自动禁用不可进入的年份和月份。

vue
<xtf-calendar current="2026-06-01" show-month-picker />

5. 多选与禁选日期

多选模式可结合静态禁选、日期区间和动态禁选函数使用:

vue
<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 插槽可重绘日期格:

vue
<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 | 强制使用范围选择,优先级高于 multiplemode | 日期区间 | | multiple | Boolean | false | 强制使用多选,优先级低于 range、高于 mode | 多日期选择 | | mode | String | 'single' | 选择模式:single / multiple / range;非法值回退单选 | 未使用 rangemultiple 时 | | 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 项的 typeblocked 时是否禁止选择 | 业务关闭日期 | | 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月' | 标题年月格式,支持 YYYYMM 占位符 | 标题文案 | | showWatermark | Boolean | false | 是否显示底部背景水印 | 日历主题 | | watermarkText / watermarkStyle | String / String \| Object \| Array | '' / '' | 水印文案,默认当前面板年份;以及水印颜色、透明度等自由样式 | 品牌化背景 | | watermarkSize | String \| Number | '' | 水印字号,数字按 rpx 处理 | 水印尺寸 | | watermarkPosition | String | 'bottom-center' | 水印预设位置:centertop-lefttop-rightbottom-leftbottom-rightbottom-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 数组每项支持的字段

字段类型默认值说明
dateString | Date-对应日期
color / labelString''圆点颜色、日期下方文案
style / cellStyleString | Object''日期单元格样式,cellStyle 优先
classNameString''日期单元格类名

statuses 数组每项支持的字段

字段类型默认值说明
dateString | Date-对应日期
typeString''状态类型;busyblocked 有内置样式
label / color / textColorString''状态文案、状态色、文案颜色
style / cellStyle / classNameString | Object / String''日期单元格样式与类名

shortcuts 数组每项支持的字段

字段类型默认值说明
keyString | Number自动生成快捷项唯一标识
labelString'快捷日期'快捷项文案
valueString | 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 })typeselectclearshortcut
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 })被拒绝的日期和实际模式

事件使用示例

vue
<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) — 切换展示月份

minDatemaxDate 限制;越界时不执行也不触发事件。

参数类型默认值说明
offsetNumber-负数切上月,正数切下月

返回值void

使用示例: this.$refs.calendar.changeMonth(1)

2. clearSelection() — 清空当前选择

只读状态下不会执行。

返回值void

使用示例: this.$refs.calendar.clearSelection()

3. confirmSelection() — 触发当前选择的确认事件

不要求选择完整范围,监听 confirmcompleted 判断是否可提交。

返回值void

使用示例:

vue
<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 }覆盖单个日期格内容;dayvaluedateisTodayisDisabledisSelectedisInRangestatusLabelmarkLabel 等状态
footer{ value, selectedValues, selectionText, clear, confirm }覆盖底部区域,可调用 clear()confirm() 执行组件内置操作

主题说明

  • 选中日期使用 --xtf-calendar-active-color--xtf-calendar-active-text,可由 activeColoractiveTextColor 局部覆盖。
  • 范围中间日期使用 --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 变量。

MIT Licensed