js 实现自定义日历

以日历的形式,展示支出数据

SalesCalendar组件

import { FC, useState, useEffect } from 'react';
import styles from './index.module.scss';
interface ISalesCalendar {
  SalesData: any;
  year: number;
  month: number;
}
const SalesCalendar: FC<ISalesCalendar> = (props: ISalesCalendar) => {
  const { SalesData, year, month } = props;

  const [currentDate, setCurrentDate] = useState<string>('');

  useEffect(() => {
    const today = new Date();
    setCurrentDate(today.toISOString().split('T')[0]); // 格式化为 YYYY-MM-DD
  }, []);

  // 获取指定月份的第一天是星期几,以及该月的天数
  const getMonthInfo = (year: number, month: number) => {
    // 获取该月的第一天
    const firstDay = new Date(year, month - 1, 1);
    const firstDayOfWeek = firstDay.getDay(); // 获取第一天是星期几
    const daysInMonth = new Date(year, month, 0).getDate(); // 获取该月的天数

    return { firstDayOfWeek, daysInMonth };
  };
  // 获取该月的日历数据
  const { firstDayOfWeek, daysInMonth } = getMonthInfo(year, month);

  // 将 SalesData 转换为一个对象,方便通过日期查找对应的收入
  const salesMap: { [key: string]: number } = {};
  SalesData.forEach((item: any) => {
    salesMap[item.data] = item.coins;
  });
  // 获取当前月的所有日期和对应的收入
  const calendarDays: any = Array.from({ length: daysInMonth }, (_, i) => {
    const day = i + 1;
    const formattedDate = `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`;
    return {
      day,
      coins: salesMap[formattedDate] || 0, // 如果没有对应的收入,则为 0
      formattedDate,
    };
  });
  // 填充日历,添加前置空白(补齐到第一天的星期几)
  const calendarCells = Array.from({ length: firstDayOfWeek })
    .map(() => null)
    .concat(calendarDays);
  // 获取当前日期的高亮样式
  const isToday = (date: string) => date === currentDate;
  console.log(Array.from({ length: firstDayOfWeek }), firstDayOfWeek, calendarCells);

  return (
    <div className={styles.sales_calendar}>
      {/* 日历头部 */}
      <div className={'flex f-ai-c f-jc-sb'}>
        {['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT'].map(day => (
          <div className={styles.name} key={day} style={{}}>
            {day}
          </div>
        ))}
      </div>

      <div className="days" style={{ display: 'flex', flexWrap: 'wrap' }}>
        {calendarCells.map((cell, index) => {
          if (cell === null) {
            return <div key={index} style={{ width: '14%', height: '60px' }}></div>;
          }

          const { day, coins, formattedDate } = cell;

          return (
            <div
              key={formattedDate}
              style={{
                width: '14%',
                height: '80px',
                textAlign: 'center',
                padding: '5px',
                backgroundColor: isToday(formattedDate) ? '#f39c12' : '#ecf0f1',
                border: '1px solid #bdc3c7',
                borderRadius: '5px',
                marginBottom: '5px',
                position: 'relative',
              }}
            >
              <div>{day}</div>
              <div style={{ fontSize: '12px', color: '#2c3e50' }}>{coins > 0 ? `${coins} coins` : ''}</div>
              {isToday(formattedDate) && (
                <div
                  style={{
                    position: 'absolute',
                    top: '5px',
                    right: '5px',
                    fontSize: '12px',
                    color: 'white',
                    backgroundColor: 'red',
                    padding: '2px 5px',
                    borderRadius: '5px',
                  }}
                >
                  今天
                </div>
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
};
export default SalesCalendar;

运用

const SalesData = [
  { data: '2025-01-01', 支出: 1000 },
  { data: '2025-01-02', 支出: 3000 },
  { data: '2025-01-03', 支出: 5000 },
  { data: '2025-01-04', 支出: 7000 },
  { data: '2025-01-05', 支出: 9000 },
  { data: '2025-01-06', 支出: 11000 },
  { data: '2025-01-07', 支出: 13000 },
  { data: '2025-01-08', 支出: 15000 },
  { data: '2025-01-09', 支出: 17000 },
  { data: '2025-01-10', 支出: 19000 },
];
 <SalesCalendar SalesData={SalesData} year={2025} month={1} />

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值