首页 > 其他分享 >可折叠,可标记日历

可折叠,可标记日历

时间:2024-08-15 17:15:35浏览次数:8  
标签:flex const 标记 日历 height width background 可折叠 day

样式:

实现代码

index.tsx

import { Image } from '@tarojs/components';
import View from '@/components/GymComponents/GymView';
import { useState } from 'react';
import classnames from 'classnames';
import dayjs from 'dayjs';
import styles from './index.module.scss';

const weekdaysList = ['日', '一', '二', '三', '四', '五', '六'];

// 获取当月天数据
const getWeekListByMonth = (monthObj: dayjs.Dayjs, selectedDay: string) => {
  const firstMonthDay = monthObj.startOf('month');
  const lastMonthDay = monthObj.endOf('month');
  const firstShowDay = firstMonthDay.startOf('week');
  const lastShowDay = lastMonthDay.endOf('week');

  const weekList = [];
  let selectedDayListIndex = 0;
  let weekListIndex = 0;

  for (let day = firstShowDay; day.isBefore(lastShowDay); day = day.add(7, 'day')) {
    const dayList = [];
    for (let index = 0; index < 7; index++) {
      const currentDay = day.add(index, 'day');
      dayList.push(currentDay);

      // 获取选中行
      if (currentDay.format('YYYY-MM-DD') == selectedDay) {
        selectedDayListIndex = weekListIndex;
      }
    }
    weekListIndex++;

    weekList.push(dayList);
  }

  return { weekList, selectedDayListIndex };
};

// 单元格处理
const MonthCell = props => {
  const { day, currentMonth, selectedDay, onClick, historyDateList } = props;

  const currentMonthText = currentMonth.format('YYYY.MM');
  const dayMonthText = day.format('YYYY.MM');

  if (currentMonthText !== dayMonthText) {
    return <View className={styles.monthCell} />;
  }

  const todayText = dayjs().format('YYYY-MM-DD');
  const dayText: string = day.format('YYYY-MM-DD');
  const disable = day.isBefore(dayjs(), 'day');

  const onHandleItem = (disable: boolean) => {
    if (disable) {
      return;
    }
    onClick && onClick(dayText);
  };

  return (
    <View onClick={() => onHandleItem(disable)} className={styles.monthCell}>
      <View
        className={classnames(styles.monthCellValue, {
          [styles.monthCellValueGrey]: disable,
          [styles.monthCellValueToday]: todayText === dayText,
          [styles.monthCellSelected]: selectedDay === dayText,
        })}
      >
        {todayText === dayText ? '今' : day.format('D')}
      </View>
      {historyDateList.includes(dayText) && !disable && <View className={styles.monthCellPoint} />}
    </View>
  );
};

interface calenderProps {
  onChangeMonth?: (val: dayjs.Dayjs) => void;
  onChangeSelect?: (val: string) => void;
  historyDateList?: string[];
  focusDay?: string;
}

const CourseCalender = (props: calenderProps) => {
  const {
    onChangeSelect,
    historyDateList = [],
    onChangeMonth,
    focusDay = dayjs().format('YYYY-MM-DD'),
  } = props;
  const today = dayjs().hour(0).minute(0).second(0).millisecond(0);
  const todayMonth = today.clone().date(1);
  const [currentMonth, setCurrentMonth] = useState(todayMonth);
  const [selectedDay, setSelectedDay] = useState(focusDay);
  const [showOneLine, setShowOneLine] = useState(true);
  const hasPreMonth = todayMonth.isBefore(currentMonth);
  const { weekList = [], selectedDayListIndex } = getWeekListByMonth(currentMonth, selectedDay);

  const handlePreMonth = () => {
    if (hasPreMonth) {
      const preMonth = currentMonth.clone().subtract(1, 'month');
      setCurrentMonth(preMonth);
      onChangeMonth && onChangeMonth(preMonth);

      // 切换月份日期默认全展示
      setShowOneLine(false);
    }
  };

  const handleNextMonth = () => {
    const nextMonth = currentMonth.clone().add(1, 'month');
    setCurrentMonth(nextMonth);
    onChangeMonth && onChangeMonth(nextMonth);

    // 切换月份日期默认全展示
    setShowOneLine(false);
  };

  const onHandleMonthCell = (dayText: string) => {
    setSelectedDay(dayText);
    onChangeSelect && onChangeSelect(dayText);
  };

  const onHandleIcon = (showIcon: boolean) => {
    if (!showIcon) {
      return;
    }
    setShowOneLine(!showOneLine);
  };

  return (
    <View className={styles.courseCalender}>
      <View className={styles.calenderHead}>
        <View className={styles.headLeft}>{currentMonth.format('YYYY年MM月')}</View>
        <View className={styles.headRight}>
          <View
            className={classnames(styles.leftIcon, { [styles.leftIconGrey]: !hasPreMonth })}
            onClick={handlePreMonth}
          />
          <View
            className={classnames(styles.rightIcon, { [styles.rightIconGrey]: false })}
            onClick={handleNextMonth}
          />
        </View>
      </View>

      <View className={styles.calenderContent}>
        <View className={styles.calenderWeek}>
          {weekdaysList.map((item, index) => (
            <View className={styles.calenderWeekItem} key={index}>
              {item}
            </View>
          ))}
        </View>

        <View className={styles.calenderMonth}>
          {(showOneLine ? [weekList[selectedDayListIndex]] : weekList).map(
            (dayList, dayListIndex) => (
              <View className={styles.calenderMonthRow} key={dayListIndex}>
                {dayList.map(day => (
                  <MonthCell
                    key={day}
                    day={day}
                    currentMonth={currentMonth}
                    historyDateList={historyDateList}
                    selectedDay={selectedDay}
                    onClick={(dayText: string) => onHandleMonthCell(dayText)}
                  />
                ))}
              </View>
            ),
          )}
        </View>
      </View>

      <View
        className={styles.calenderFooter}
        onClick={() => onHandleIcon(currentMonth.format('YYYY-MM') == selectedDay.slice(0, 7))}
      >
        {currentMonth.format('YYYY-MM') == selectedDay.slice(0, 7) && (
          <Image
            className={styles.footerIcon}
            webp
            mode="aspectFill"
            src={
              showOneLine
                ? 'https://img.alicdn.com/imgextra/i3/O1CN015sI3l8283imvg6YPJ_!!6000000007877-2-tps-48-48.png'
                : 'https://img.alicdn.com/imgextra/i4/O1CN01U8KCQe1DlINDEFEQq_!!6000000000256-2-tps-48-48.png'
            }
            lazyLoad
          />
        )}
      </View>
    </View>
  );
};

export default CourseCalender;

index.less

.courseCalender {
  width: 686px;
  background-color: #fff;
  border-radius: 8px;
  overflow: hidden;

  .calenderHead {
    width: 100%;
    height: 72px;
    background: #222;
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
    padding: 0 16px 0 24px;

    .headLeft {
      font-family: Akrobat-ExtraBold;
      font-size: 32px;
      color: #fff;
    }

    .headRight {
      display: flex;
      flex-direction: row;

      .leftIcon,
      .rightIcon {
        width: 48px;
        height: 48px;
        background-repeat: no-repeat;
        background-size: contain;
        margin-left: 8px;
      }

      .leftIcon {
        background-image: url('https://img.alicdn.com/imgextra/i2/O1CN01buoF9i1Ntfm2Xi8Vx_!!6000000001628-2-tps-48-48.png');
      }

      .leftIconGrey {
        background-image: url('https://img.alicdn.com/imgextra/i2/O1CN01W9Cdbb29VUPwL5opO_!!6000000008073-2-tps-48-48.png');
      }

      .rightIcon {
        background-image: url('https://img.alicdn.com/imgextra/i3/O1CN01lgfwCS1CE1zRUe9X7_!!6000000000048-2-tps-48-48.png');
      }

      .rightIconGrey {
        background-image: url('https://img.alicdn.com/imgextra/i1/O1CN01INUsTs1zv0KCwndMy_!!6000000006775-2-tps-48-48.png');
      }

    }
  }

  .calenderContent {
    width: 100%;
    padding: 0 12px;
    display: flex;
    flex-direction: column;
    align-items: center;

    .calenderWeek {
      width: 100%;
      height: 82px;
      display: flex;
      flex-direction: row;
      justify-content: space-around;
      align-items: center;

      .calenderWeekItem {
        width: 64px;
        height: 64px;
        font-family: PingFangSC-Regular;
        line-height: 64px;
        text-align: center;
        font-size: 22px;
        color: #666;
        flex-shrink: 0;
      }
    }

    .calenderMonth {
      width: 100%;

      .calenderMonthRow {
        width: 100%;
        height: 82px;
        display: flex;
        flex-direction: row;
        justify-content: space-around;
        align-items: center;
      }

    }
  }

  .calenderFooter {
    width: 100%;
    height: 48px;
    display: flex;
    align-items: center;
    justify-content: center;

    .footerIcon {
      width: 48px;
      height: 48px;
    }
  }

}

.monthCell {
  width: 64px;
  height: 64px;
  flex-shrink: 0;
  position: relative;

  .monthCellValue {
    width: 100%;
    height: 100%;
    font-family: PingFangSC-Regular;
    line-height: 64px;
    text-align: center;
    font-size: 32px;
    color: #666;
    border-radius: 50%;
  }

  .monthCellValueGrey {
    color: rgba(102, 102, 102, 0.3);
  }

  .monthCellValueToday {
    font-family: PingFangSC-Regular;
    font-size: 28px;
    color: #666;
    background-color: #f5f5f5;
  }

  .monthCellSelected {
    color: #f5f5f5;
    background-color: #ff6022;
  }

  .monthCellPoint {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background-color: #ff6022;
    position: absolute;
    bottom: 6px;
    left: 28px;
  }

}

 

标签:flex,const,标记,日历,height,width,background,可折叠,day
From: https://www.cnblogs.com/yujiawen/p/18361390

相关文章

  • 线段树+懒标记 (区间修改,区间查询)
    原作者:董晓P3372【模板】线段树1//结构体版#include<cstring>#include<iostream>#include<algorithm>usingnamespacestd;#defineN100005#defineLLlonglong#definelcu<<1#definercu<<1|1LLw[N];structTree{//线段树LLl,r,......
  • 0228-TCP 的标记和选项
    环境Time2022-11-24WSL-Ubuntu22.04Rust1.65.0pnet0.31.0tun-tap0.1.3前言说明参考:https://docs.rs/pnet/latest/pnet/index.html参考:https://www.cnblogs.com/lshs/p/6038494.html目标了解TCP协议头中的flags和options字段的含义。main.rsusepnet::pa......
  • 2024-08-14:用go语言,给定两个长度分别为n和m的整数数组nums和changeIndices,下标从1开始
    2024-08-14:用go语言,给定两个长度分别为n和m的整数数组nums和changeIndices,下标从1开始。初始时,nums中所有下标均未标记。从第1秒到第m秒,每秒可以选择以下四种操作之一:1.选择范围[1,n]中一个下标i,将nums[i]减少1。2.将nums[changeIndices[s]]设为任意非负整数。3.选择范围......
  • 关于区间加区间查线段树的标记永久化
    单点加区间查的线段树,每个线段树区间的值代表所维护序列在这个区间的总和;区间加单点查的线段树,每个线段树区间的值代表对这个区间总体加了多少。区间加区间查的线段树可以通过综合两种思想实现标记的永久化。线段树将每一个修改或查询区间拆分为\(O(\logw)\)个线段树区间,只要......
  • 分享一个200年日历的黄道吉日sql数据打包供下载以及推荐一个好用的基于bootstrap的颜
    一、分享一个200年日历的黄道吉日sql数据打包    自己抓取的一套200年(1900-2100)全部日期的黄道吉日数据,分享出来,也在此备份以备以后自己要用。包括每天年月日,干支年,干支月,干支日,星期,阳历,农历,阴历月份,阴历日期,星座,胎神,五行,冲,煞,生肖,吉日,值......
  • 使用 Confluence API 的日历信息
    我有一个Confluence页面,里面有一个日历(请检查下面的照片)。日历我正在尝试从此日历中提取信息,例如每天有多少个事件。仅此而已。我使用了来自StackOverflow的代码,该代码使用API读取Confluence页面。但JSON响应不包含有关页面内日历的任何数据。`import......
  • 在 TfidfVectorizer 标记化后删除二元组
    我正在尝试删除由TfidfVectorizer创建的二元组。我正在使用text.TfidfVectorizer,以便我可以使用自己的预处理器函数。Initfromsklearn.feature_extraction.textimportENGLISH_STOP_WORDSasstop_wordsfromsklearn.feature_extraction.textimportTfidfV......
  • LeetCode 136场双周赛 Q4. 标记所有节点需要的时间
    这道题也是一道比较经典的树形dp模板题;太久没写了,赛时一眼就想到了,但是敲的时候摸索了半天,还是没敲出来;首先看题目,需要求出无向树上从每个节点为树根节点到其他所有节点中最长路径的值,然后每条边的距离其实就是,如果目的地是奇数距离为1,目的地是偶数距离为2那么这个逻辑很简单,其......
  • 我可以在 Folium 地图上添加一系列标记吗?
    假设我有一个列表,或pandas系列,或纬度经度对。使用Folium,我可以使用coords=[46.8354,-121.7325]map_4=folium.Map(location=[46.8527,-121.7649],tiles='StamenTerrain',zoom_start=13)folium.Marker(location=coords).add_to(map_4)绘......
  • error C2589: “(”:“::”右边的非法标记错误的处理
    问题:errorC2589:“(”:“::”右边的非法标记错误的处理标准库在<algorithm>头中定义了两个模板函数std::min()和std::max(),通常用它可以计算某个值对的最小值和最大值。而在VisualC++使用会发生名字min和max与<windows.h>中传统的min/max宏定义有冲突的现象。可以用如下方......