| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836 |
- <template>
- <view class="cl-calendar" :class="[pt.className]">
- <!-- 年月选择器弹窗 -->
- <calendar-picker
- :year="currentYear"
- :month="currentMonth"
- :ref="refs.set('picker')"
- @change="onYearMonthChange"
- ></calendar-picker>
- <!-- 头部导航栏 -->
- <view class="cl-calendar__header" v-if="showHeader">
- <!-- 上一月按钮 -->
- <view
- class="cl-calendar__header-prev"
- :class="{ 'is-dark': isDark }"
- @tap.stop="gotoPrevMonth"
- >
- <cl-icon name="arrow-left-s-line"></cl-icon>
- </view>
- <!-- 当前年月显示区域 -->
- <view class="cl-calendar__header-date" @tap="refs.open('picker')">
- <slot name="current-date">
- <cl-text :pt="{ className: 'text-lg' }">{{
- $t(`{year}年{month}月`, { year: currentYear, month: currentMonth })
- }}</cl-text>
- </slot>
- </view>
- <!-- 下一月按钮 -->
- <view
- class="cl-calendar__header-next"
- :class="{ 'is-dark': isDark }"
- @tap.stop="gotoNextMonth"
- >
- <cl-icon name="arrow-right-s-line"></cl-icon>
- </view>
- </view>
- <!-- 星期标题行 -->
- <view class="cl-calendar__weeks" :style="{ gap: `${cellGap}px` }" v-if="showWeeks">
- <view class="cl-calendar__weeks-item" v-for="weekName in weekLabels" :key="weekName">
- <cl-text>{{ weekName }}</cl-text>
- </view>
- </view>
- <!-- 日期网格容器 -->
- <view
- class="cl-calendar__view"
- ref="viewRef"
- :style="{ height: `${viewHeight}px`, gap: `${cellGap}px` }"
- @tap="onTap"
- >
- <!-- #ifndef APP -->
- <view
- class="cl-calendar__view-row"
- :style="{ gap: `${cellGap}px` }"
- v-for="(weekRow, rowIndex) in dateMatrix"
- :key="rowIndex"
- >
- <view
- class="cl-calendar__view-cell"
- v-for="(dateCell, cellIndex) in weekRow"
- :key="cellIndex"
- :class="{
- 'is-selected': dateCell.isSelected,
- 'is-range': dateCell.isRange,
- 'is-hide': dateCell.isHide,
- 'is-disabled': dateCell.isDisabled,
- 'is-today': dateCell.isToday,
- 'is-other-month': !dateCell.isCurrentMonth
- }"
- :style="{
- height: cellHeight + 'px',
- backgroundColor: getCellBgColor(dateCell)
- }"
- @click.stop="selectDateCell(dateCell)"
- >
- <!-- 顶部文本 -->
- <cl-text
- :size="20"
- :color="getCellTextColor(dateCell)"
- :pt="{
- className: 'absolute top-[2px]'
- }"
- >{{ dateCell.topText }}</cl-text
- >
- <!-- 主日期数字 -->
- <cl-text
- :color="getCellTextColor(dateCell)"
- :size="`${fontSize}px`"
- :pt="{
- className: 'font-bold'
- }"
- >{{ dateCell.date }}</cl-text
- >
- <!-- 底部文本 -->
- <cl-text
- :size="20"
- :color="getCellTextColor(dateCell)"
- :pt="{
- className: 'absolute bottom-[2px]'
- }"
- >{{ dateCell.bottomText }}</cl-text
- >
- </view>
- </view>
- <!-- #endif -->
- </view>
- </view>
- </template>
- <script lang="ts" setup>
- import { computed, nextTick, onMounted, ref, watch, type PropType } from "vue";
- import { ctx, dayUts, first, isDark, isHarmony, parsePt, useRefs } from "@/cool";
- import CalendarPicker from "./picker.uvue";
- import { $t, t } from "@/locale";
- import type { ClCalendarDateConfig, ClCalendarMode } from "../../types";
- import { useSize } from "../../hooks";
- defineOptions({
- name: "cl-calendar"
- });
- // 日期单元格数据结构
- type DateCell = {
- date: string; // 显示的日期数字
- isCurrentMonth: boolean; // 是否属于当前显示月份
- isToday: boolean; // 是否为今天
- isSelected: boolean; // 是否被选中
- isRange: boolean; // 是否在选择范围内
- fullDate: string; // 完整日期格式 YYYY-MM-DD
- isDisabled: boolean; // 是否被禁用
- isHide: boolean; // 是否隐藏显示
- topText: string; // 顶部文案
- bottomText: string; // 底部文案
- color: string; // 颜色
- };
- // 组件属性定义
- const props = defineProps({
- // 透传样式配置
- pt: {
- type: Object,
- default: () => ({})
- },
- // 当前选中的日期值(单选模式)
- modelValue: {
- type: String as PropType<string | null>,
- default: null
- },
- // 选中的日期数组(多选/范围模式)
- date: {
- type: Array as PropType<string[]>,
- default: () => []
- },
- // 日期选择模式:单选/多选/范围选择
- mode: {
- type: String as PropType<ClCalendarMode>,
- default: "single"
- },
- // 日期配置
- dateConfig: {
- type: Array as PropType<ClCalendarDateConfig[]>,
- default: () => []
- },
- // 开始日期,可选日期的开始
- start: {
- type: String
- },
- // 结束日期,可选日期的结束
- end: {
- type: String
- },
- // 设置年份
- year: {
- type: Number
- },
- // 设置月份
- month: {
- type: Number
- },
- // 是否显示其他月份的日期
- showOtherMonth: {
- type: Boolean,
- default: true
- },
- // 是否显示头部导航栏
- showHeader: {
- type: Boolean,
- default: true
- },
- // 是否显示星期
- showWeeks: {
- type: Boolean,
- default: true
- }
- });
- // 事件发射器定义
- const emit = defineEmits(["update:modelValue", "update:date", "change"]);
- // 透传样式属性类型
- type PassThrough = {
- className?: string;
- };
- // 解析透传样式配置
- const pt = computed(() => parsePt<PassThrough>(props.pt));
- // 字体大小
- const { getPxValue } = useSize();
- // 主色
- const color = ref(ctx.color["primary-500"] as string);
- // 单元格高度
- const cellHeight = ref(66);
- // 单元格间距
- const cellGap = ref(0);
- // 字体大小
- const fontSize = computed(() => {
- // #ifdef APP
- return getPxValue("14px");
- // #endif
- // #ifndef APP
- return 14;
- // #endif
- });
- // 当前月份日期颜色
- const textColor = computed(() => {
- return isDark.value ? "white" : (ctx.color["surface-700"] as string);
- });
- // 其他月份日期颜色
- const textOtherMonthColor = computed(() => {
- return isDark.value
- ? (ctx.color["surface-500"] as string)
- : (ctx.color["surface-300"] as string);
- });
- // 禁用日期颜色
- const textDisabledColor = computed(() => {
- return isDark.value
- ? (ctx.color["surface-500"] as string)
- : (ctx.color["surface-300"] as string);
- });
- // 今天日期颜色
- const textTodayColor = ref("#ff6b6b");
- // 选中日期颜色
- const textSelectedColor = ref("#ffffff");
- // 选中日期背景颜色
- const bgSelectedColor = ref(color.value);
- // 范围选择背景颜色
- const bgRangeColor = ref(isHarmony() ? (ctx.color["primary-50"] as string) : color.value + "11");
- // 组件引用管理器
- const refs = useRefs();
- // 日历视图DOM元素引用
- const viewRef = ref<UniElement | null>(null);
- // 当前显示的年份
- const currentYear = ref(0);
- // 当前显示的月份
- const currentMonth = ref(0);
- // 视图高度
- const viewHeight = computed(() => {
- return cellHeight.value * 6;
- });
- // 单元格宽度
- const cellWidth = ref(0);
- // 星期标签数组
- const weekLabels = computed(() => {
- return [t("周日"), t("周一"), t("周二"), t("周三"), t("周四"), t("周五"), t("周六")];
- });
- // 日历日期矩阵数据(6行7列)
- const dateMatrix = ref<DateCell[][]>([]);
- // 当前选中的日期列表
- const selectedDates = ref<string[]>([]);
- /**
- * 获取日历视图元素的位置信息
- */
- async function getViewRect(): Promise<DOMRect | null> {
- return viewRef.value!.getBoundingClientRectAsync();
- }
- /**
- * 判断指定日期是否被选中
- * @param dateStr 日期字符串 YYYY-MM-DD
- */
- function isDateSelected(dateStr: string): boolean {
- if (props.mode == "single") {
- // 单选模式:检查是否为唯一选中日期
- return selectedDates.value[0] == dateStr;
- } else {
- // 多选/范围模式:检查是否在选中列表中
- return selectedDates.value.includes(dateStr);
- }
- }
- /**
- * 判断指定日期是否被禁用
- * @param dateStr 日期字符串 YYYY-MM-DD
- */
- function isDateDisabled(dateStr: string): boolean {
- // 大于开始日期
- if (props.start != null) {
- if (dayUts(dateStr).isBefore(dayUts(props.start))) {
- return true;
- }
- }
- // 小于结束日期
- if (props.end != null) {
- if (dayUts(dateStr).isAfter(dayUts(props.end))) {
- return true;
- }
- }
- return props.dateConfig.some((config) => config.date == dateStr && config.disabled == true);
- }
- /**
- * 判断指定日期是否在选择范围内(不包括端点)
- * @param dateStr 日期字符串 YYYY-MM-DD
- */
- function isDateInRange(dateStr: string): boolean {
- // 仅范围选择模式且已选择两个端点时才有范围
- if (props.mode != "range" || selectedDates.value.length != 2) {
- return false;
- }
- const [startDate, endDate] = selectedDates.value;
- const currentDate = dayUts(dateStr);
- return currentDate.isAfter(startDate) && currentDate.isBefore(endDate);
- }
- /**
- * 获取单元格字体颜色
- * @param dateCell 日期单元格数据
- * @returns 字体颜色
- */
- function getCellTextColor(dateCell: DateCell): string {
- // 选中的日期文字颜色
- if (dateCell.isSelected) {
- return textSelectedColor.value;
- }
- if (dateCell.color != "") {
- return dateCell.color;
- }
- // 范围选择日期颜色
- if (dateCell.isRange) {
- return color.value;
- }
- // 禁用的日期颜色
- if (dateCell.isDisabled) {
- return textDisabledColor.value;
- }
- // 今天日期颜色
- if (dateCell.isToday) {
- return textTodayColor.value;
- }
- // 当前月份日期颜色
- if (dateCell.isCurrentMonth) {
- return textColor.value;
- }
- // 其他月份日期颜色
- return textOtherMonthColor.value;
- }
- /**
- * 获取单元格背景颜色
- * @param dateCell 日期单元格数据
- * @returns 背景颜色
- */
- function getCellBgColor(dateCell: DateCell): string {
- if (dateCell.isSelected) {
- return bgSelectedColor.value;
- }
- if (dateCell.isRange) {
- return bgRangeColor.value;
- }
- return "transparent";
- }
- /**
- * 计算并生成日历矩阵数据
- * 生成6行7列共42个日期,包含上月末尾和下月开头的日期
- */
- function calculateDateMatrix() {
- const weekRows: DateCell[][] = [];
- const todayStr = dayUts().format("YYYY-MM-DD"); // 今天的日期字符串
- // 获取当前月第一天
- const monthFirstDay = dayUts(`${currentYear.value}-${currentMonth.value}-01`);
- const firstDayWeekIndex = monthFirstDay.getDay(); // 第一天是星期几 (0=周日, 6=周六)
- // 计算日历显示的起始日期(可能是上个月的日期)
- const calendarStartDate = monthFirstDay.subtract(firstDayWeekIndex, "day");
- // 生成6周的日期数据(6行 × 7列 = 42天)
- let iterateDate = calendarStartDate;
- for (let weekIndex = 0; weekIndex < 6; weekIndex++) {
- const weekDates: DateCell[] = [];
- for (let dayIndex = 0; dayIndex < 7; dayIndex++) {
- const fullDateStr = iterateDate.format("YYYY-MM-DD");
- const nativeDate = iterateDate.toDate();
- const dayNumber = nativeDate.getDate();
- // 判断是否属于当前显示月份
- const belongsToCurrentMonth =
- nativeDate.getMonth() + 1 == currentMonth.value &&
- nativeDate.getFullYear() == currentYear.value;
- // 日期配置
- const dateConfig = props.dateConfig.find((config) => config.date == fullDateStr);
- // 构建日期单元格数据
- const dateCell = {
- date: `${dayNumber}`,
- isCurrentMonth: belongsToCurrentMonth,
- isToday: fullDateStr == todayStr,
- isSelected: isDateSelected(fullDateStr),
- isRange: isDateInRange(fullDateStr),
- fullDate: fullDateStr,
- isDisabled: isDateDisabled(fullDateStr),
- isHide: false,
- topText: dateConfig?.topText ?? "",
- bottomText: dateConfig?.bottomText ?? "",
- color: dateConfig?.color ?? ""
- } as DateCell;
- // 根据配置决定是否隐藏相邻月份的日期
- if (!props.showOtherMonth && !belongsToCurrentMonth) {
- dateCell.isHide = true;
- }
- weekDates.push(dateCell);
- iterateDate = iterateDate.add(1, "day"); // 移动到下一天
- }
- weekRows.push(weekDates);
- }
- dateMatrix.value = weekRows;
- }
- /**
- * 使用Canvas绘制日历(仅APP端)
- * Web端使用DOM渲染,APP端使用Canvas提升性能
- */
- async function renderCalendar() {
- // #ifdef APP
- await nextTick(); // 等待DOM更新完成
- const ctx = viewRef.value!.getDrawableContext();
- if (ctx == null) return;
- ctx!.reset(); // 清空画布
- /**
- * 绘制单个日期单元格
- * @param dateCell 日期单元格数据
- * @param colIndex 列索引 (0-6)
- * @param rowIndex 行索引 (0-5)
- */
- function drawSingleCell(dateCell: DateCell, colIndex: number, rowIndex: number) {
- // 计算单元格位置
- const cellX = colIndex * cellWidth.value;
- const cellY = rowIndex * cellHeight.value;
- const centerX = cellX + cellWidth.value / 2;
- const centerY = cellY + cellHeight.value / 2;
- // 绘制背景(选中状态或范围状态)
- if (dateCell.isSelected || dateCell.isRange) {
- const padding = cellGap.value; // 使用间距作为内边距
- const bgX = cellX + padding;
- const bgY = cellY + padding;
- const bgWidth = cellWidth.value - padding * 2;
- const bgHeight = cellHeight.value - padding * 2;
- // 设置背景颜色
- if (dateCell.isSelected) {
- ctx!.fillStyle = bgSelectedColor.value;
- }
- if (dateCell.isRange) {
- ctx!.fillStyle = bgRangeColor.value;
- }
- ctx!.fillRect(bgX, bgY, bgWidth, bgHeight); // 绘制背景矩形
- }
- // 获取单元格文字颜色
- const cellTextColor = getCellTextColor(dateCell);
- ctx!.textAlign = "center";
- // 绘制顶部文本
- if (dateCell.topText != "") {
- ctx!.font = `${Math.floor(fontSize.value * 0.75)}px sans-serif`;
- ctx!.fillStyle = cellTextColor;
- const topY = cellY + 16; // 距离顶部
- ctx!.fillText(dateCell.topText, centerX, topY);
- }
- // 绘制主日期数字
- ctx!.font = `${fontSize.value}px sans-serif`;
- ctx!.fillStyle = cellTextColor;
- const textOffsetY = (fontSize.value / 2) * 0.7;
- ctx!.fillText(dateCell.date.toString(), centerX, centerY + textOffsetY);
- // 绘制底部文本
- if (dateCell.bottomText != "") {
- ctx!.font = `${Math.floor(fontSize.value * 0.75)}px sans-serif`;
- ctx!.fillStyle = cellTextColor;
- const bottomY = cellY + cellHeight.value - 8; // 距离底部
- ctx!.fillText(dateCell.bottomText, centerX, bottomY);
- }
- }
- // 获取容器尺寸信息
- const viewRect = await getViewRect();
- if (viewRect == null) {
- return;
- }
- // 计算单元格宽度(总宽度除以7列)
- const cellSize = viewRect.width / 7;
- // 更新渲染配置
- cellWidth.value = cellSize;
- // 遍历日期矩阵进行绘制
- for (let rowIndex = 0; rowIndex < dateMatrix.value.length; rowIndex++) {
- const weekRow = dateMatrix.value[rowIndex];
- for (let colIndex = 0; colIndex < weekRow.length; colIndex++) {
- const dateCell = weekRow[colIndex];
- if (!dateCell.isHide) {
- drawSingleCell(dateCell, colIndex, rowIndex);
- }
- }
- }
- ctx!.update(); // 更新画布显示
- // #endif
- }
- /**
- * 处理日期单元格选择逻辑
- * @param dateCell 被点击的日期单元格
- */
- function selectDateCell(dateCell: DateCell) {
- // 隐藏或禁用的日期不可选择
- if (dateCell.isHide || dateCell.isDisabled) {
- return;
- }
- if (props.mode == "single") {
- // 单选模式:直接替换选中日期
- selectedDates.value = [dateCell.fullDate];
- emit("update:modelValue", dateCell.fullDate);
- } else if (props.mode == "multiple") {
- // 多选模式:切换选中状态
- const existingIndex = selectedDates.value.indexOf(dateCell.fullDate);
- if (existingIndex >= 0) {
- // 已选中则移除
- selectedDates.value.splice(existingIndex, 1);
- } else {
- // 未选中则添加
- selectedDates.value.push(dateCell.fullDate);
- }
- } else {
- // 范围选择模式
- if (selectedDates.value.length == 0) {
- // 第一次点击:设置起始日期
- selectedDates.value = [dateCell.fullDate];
- } else if (selectedDates.value.length == 1) {
- // 第二次点击:设置结束日期
- const startDate = dayUts(selectedDates.value[0]);
- const endDate = dayUts(dateCell.fullDate);
- if (endDate.isBefore(startDate)) {
- // 结束日期早于开始日期时自动交换
- selectedDates.value = [dateCell.fullDate, selectedDates.value[0]];
- } else {
- selectedDates.value = [selectedDates.value[0], dateCell.fullDate];
- }
- } else {
- // 已有范围时重新开始选择
- selectedDates.value = [dateCell.fullDate];
- }
- }
- // 发射更新事件
- emit("update:date", [...selectedDates.value]);
- emit("change", selectedDates.value);
- // 重新计算日历数据并重绘
- calculateDateMatrix();
- renderCalendar();
- }
- /**
- * 处理年月选择器的变化事件
- * @param yearMonthArray [年份, 月份] 数组
- */
- function onYearMonthChange(yearMonthArray: number[]) {
- currentYear.value = yearMonthArray[0];
- currentMonth.value = yearMonthArray[1];
- // 重新计算日历数据并重绘
- calculateDateMatrix();
- renderCalendar();
- }
- /**
- * 处理点击事件(APP端点击检测)
- */
- async function onTap(e: UniPointerEvent) {
- // 获取容器位置信息
- const viewRect = await getViewRect();
- if (viewRect == null) {
- return;
- }
- // 计算触摸点相对于容器的坐标
- const relativeX = e.clientX - viewRect.left;
- const relativeY = e.clientY - viewRect.top;
- // 根据坐标计算对应的行列索引
- const columnIndex = Math.floor(relativeX / cellWidth.value);
- const rowIndex = Math.floor(relativeY / cellHeight.value);
- // 边界检查:确保索引在有效范围内
- if (
- rowIndex < 0 ||
- rowIndex >= dateMatrix.value.length ||
- columnIndex < 0 ||
- columnIndex >= 7
- ) {
- return;
- }
- const targetDateCell = dateMatrix.value[rowIndex][columnIndex];
- selectDateCell(targetDateCell);
- }
- /**
- * 切换到上一个月
- */
- function gotoPrevMonth() {
- const [newYear, newMonth] = dayUts(`${currentYear.value}-${currentMonth.value}-01`)
- .subtract(1, "month")
- .toArray();
- currentYear.value = newYear;
- currentMonth.value = newMonth;
- // 重新计算并渲染日历
- calculateDateMatrix();
- renderCalendar();
- }
- /**
- * 切换到下一个月
- */
- function gotoNextMonth() {
- const [newYear, newMonth] = dayUts(`${currentYear.value}-${currentMonth.value}-01`)
- .add(1, "month")
- .toArray();
- currentYear.value = newYear;
- currentMonth.value = newMonth;
- // 重新计算并渲染日历
- calculateDateMatrix();
- renderCalendar();
- }
- /**
- * 解析选中日期
- */
- function parseDate(flag: boolean | null = null) {
- // 根据选择模式初始化选中日期
- if (props.mode == "single") {
- selectedDates.value = props.modelValue != null ? [props.modelValue] : [];
- } else {
- selectedDates.value = [...props.date];
- }
- // 获取初始显示日期(优先使用选中日期,否则使用当前日期)
- let [year, month] = dayUts(first(selectedDates.value)).toArray();
- if (flag == true) {
- year = props.year ?? year;
- month = props.month ?? month;
- }
- currentYear.value = year;
- currentMonth.value = month;
- // 计算初始日历数据
- calculateDateMatrix();
- // 渲染日历视图
- renderCalendar();
- }
- // 组件挂载时的初始化逻辑
- onMounted(() => {
- // 解析日期
- parseDate(true);
- // 监听单选模式的值变化
- watch(
- computed(() => props.modelValue ?? ""),
- (newValue: string) => {
- selectedDates.value = [newValue];
- parseDate();
- }
- );
- // 监听多选/范围模式的值变化
- watch(
- computed(() => props.date),
- (newDateArray: string[]) => {
- selectedDates.value = [...newDateArray];
- parseDate();
- }
- );
- // 重新渲染
- watch(
- computed(() => [props.dateConfig, props.showOtherMonth]),
- () => {
- calculateDateMatrix();
- renderCalendar();
- },
- {
- deep: true
- }
- );
- });
- </script>
- <style lang="scss" scoped>
- /* 日历组件主容器 */
- .cl-calendar {
- @apply relative;
- /* 头部导航栏样式 */
- &__header {
- @apply flex flex-row items-center justify-between p-3 w-full;
- /* 上一月/下一月按钮样式 */
- &-prev,
- &-next {
- @apply flex flex-row items-center justify-center rounded-full bg-surface-100;
- width: 60rpx;
- height: 60rpx;
- /* 暗色模式适配 */
- &.is-dark {
- @apply bg-surface-700;
- }
- }
- /* 当前年月显示区域 */
- &-date {
- @apply flex flex-row items-center justify-center;
- }
- }
- /* 星期标题行样式 */
- &__weeks {
- @apply flex flex-row;
- /* 单个星期标题样式 */
- &-item {
- @apply flex flex-row items-center justify-center flex-1;
- height: 80rpx;
- }
- }
- /* 日期网格容器样式 */
- &__view {
- @apply w-full;
- // #ifndef APP
- /* 日期行样式 */
- &-row {
- @apply flex flex-row;
- }
- /* 日期单元格样式 */
- &-cell {
- @apply flex-1 flex flex-col items-center justify-center relative;
- height: 80rpx;
- /* 隐藏状态(相邻月份日期) */
- &.is-hide {
- opacity: 0;
- }
- /* 禁用状态 */
- &.is-disabled {
- @apply opacity-50;
- }
- }
- // #endif
- }
- }
- </style>
|