209 lines
9.1 KiB
HTML
209 lines
9.1 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>日历组件</title>
|
||
<link rel="stylesheet" href="../../assets/css/widgets.css">
|
||
|
||
</head>
|
||
<body>
|
||
<div class="widget glass calendar-widget">
|
||
<div class="calendar-header">
|
||
<button class="calendar-nav" id="prev-month"><</button>
|
||
<h3 id="current-month-year">2024年1月</h3>
|
||
<button class="calendar-nav" id="next-month">></button>
|
||
</div>
|
||
<div class="calendar-grid">
|
||
<!-- 星期标题 -->
|
||
<div class="calendar-weekday">日</div>
|
||
<div class="calendar-weekday">一</div>
|
||
<div class="calendar-weekday">二</div>
|
||
<div class="calendar-weekday">三</div>
|
||
<div class="calendar-weekday">四</div>
|
||
<div class="calendar-weekday">五</div>
|
||
<div class="calendar-weekday">六</div>
|
||
|
||
<!-- 日期单元格将通过JavaScript动态生成 -->
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
// 日历功能 - 重构版本
|
||
(function() {
|
||
let currentDate = new Date();
|
||
let selectedDate = null;
|
||
|
||
// 渲染日历函数
|
||
function renderCalendar() {
|
||
try {
|
||
const year = currentDate.getFullYear();
|
||
const month = currentDate.getMonth();
|
||
|
||
// 更新月份标题
|
||
const titleElement = document.getElementById('current-month-year');
|
||
if (titleElement) {
|
||
titleElement.textContent = `${year}年${month + 1}月`;
|
||
}
|
||
|
||
// 获取日历网格容器
|
||
const calendarGrid = document.querySelector('.calendar-grid');
|
||
if (!calendarGrid) {
|
||
console.error('日历网格容器未找到');
|
||
return;
|
||
}
|
||
|
||
// 保留星期标题,移除所有日期单元格
|
||
const weekdayHeaders = Array.from(calendarGrid.querySelectorAll('.calendar-weekday'));
|
||
calendarGrid.innerHTML = '';
|
||
|
||
// 重新添加星期标题
|
||
weekdayHeaders.forEach(header => calendarGrid.appendChild(header));
|
||
|
||
// 获取当月第一天和最后一天
|
||
const firstDay = new Date(year, month, 1);
|
||
const lastDay = new Date(year, month + 1, 0);
|
||
|
||
const daysInMonth = lastDay.getDate();
|
||
const startingDay = firstDay.getDay();
|
||
|
||
// 获取今天的日期用于比较
|
||
const today = new Date();
|
||
|
||
// 添加上月的最后几天
|
||
const prevMonthLastDay = new Date(year, month, 0).getDate();
|
||
for (let i = startingDay - 1; i >= 0; i--) {
|
||
const dayDiv = createDayElement(prevMonthLastDay - i, false);
|
||
dayDiv.classList.add('other-month');
|
||
calendarGrid.appendChild(dayDiv);
|
||
}
|
||
|
||
// 添加当月的天数
|
||
for (let i = 1; i <= daysInMonth; i++) {
|
||
const dayDiv = createDayElement(i, true);
|
||
dayDiv.setAttribute('data-date', `${year}-${month + 1}-${i}`);
|
||
|
||
// 高亮今天
|
||
if (i === today.getDate() && month === today.getMonth() && year === today.getFullYear()) {
|
||
dayDiv.classList.add('today');
|
||
}
|
||
|
||
// 高亮选中的日期
|
||
if (selectedDate && i === selectedDate.getDate() && month === selectedDate.getMonth() && year === selectedDate.getFullYear()) {
|
||
dayDiv.classList.add('selected');
|
||
}
|
||
|
||
calendarGrid.appendChild(dayDiv);
|
||
}
|
||
|
||
// 添加下月的开始几天,确保日历始终显示6行
|
||
const totalCells = 42; // 6行7列 = 42个单元格(包括星期标题)
|
||
const currentCells = 7 + startingDay + daysInMonth; // 7个星期标题 + 上月天数 + 当月天数
|
||
const remainingDays = totalCells - currentCells;
|
||
|
||
for (let i = 1; i <= remainingDays; i++) {
|
||
const dayDiv = createDayElement(i, false);
|
||
dayDiv.classList.add('other-month');
|
||
calendarGrid.appendChild(dayDiv);
|
||
}
|
||
} catch (error) {
|
||
console.error('渲染日历出错:', error);
|
||
}
|
||
}
|
||
|
||
// 创建日期元素
|
||
function createDayElement(day, isCurrentMonth) {
|
||
const dayDiv = document.createElement('div');
|
||
dayDiv.className = 'calendar-day';
|
||
dayDiv.textContent = day;
|
||
|
||
// 只有当前月的日期可以点击选择
|
||
if (isCurrentMonth) {
|
||
dayDiv.addEventListener('click', () => handleDayClick(day));
|
||
dayDiv.setAttribute('tabindex', '0'); // 使其可聚焦
|
||
dayDiv.addEventListener('keydown', (e) => {
|
||
if (e.key === 'Enter' || e.key === ' ') {
|
||
handleDayClick(day);
|
||
e.preventDefault();
|
||
}
|
||
});
|
||
}
|
||
|
||
return dayDiv;
|
||
}
|
||
|
||
// 处理日期点击
|
||
function handleDayClick(day) {
|
||
try {
|
||
const year = currentDate.getFullYear();
|
||
const month = currentDate.getMonth();
|
||
selectedDate = new Date(year, month, day);
|
||
|
||
// 触发日期选择事件
|
||
const event = new CustomEvent('date-selected', {
|
||
detail: { date: selectedDate }
|
||
});
|
||
document.dispatchEvent(event);
|
||
|
||
// 重新渲染以更新选中状态
|
||
renderCalendar();
|
||
} catch (error) {
|
||
console.error('处理日期点击出错:', error);
|
||
}
|
||
}
|
||
|
||
// 绑定导航按钮事件
|
||
function bindNavigationEvents() {
|
||
try {
|
||
const prevButton = document.getElementById('prev-month');
|
||
const nextButton = document.getElementById('next-month');
|
||
|
||
if (prevButton) {
|
||
prevButton.addEventListener('click', () => {
|
||
currentDate.setMonth(currentDate.getMonth() - 1);
|
||
renderCalendar();
|
||
});
|
||
}
|
||
|
||
if (nextButton) {
|
||
nextButton.addEventListener('click', () => {
|
||
currentDate.setMonth(currentDate.getMonth() + 1);
|
||
renderCalendar();
|
||
});
|
||
}
|
||
|
||
// 添加键盘导航
|
||
document.addEventListener('keydown', (e) => {
|
||
if (e.key === 'ArrowLeft') {
|
||
currentDate.setMonth(currentDate.getMonth() - 1);
|
||
renderCalendar();
|
||
} else if (e.key === 'ArrowRight') {
|
||
currentDate.setMonth(currentDate.getMonth() + 1);
|
||
renderCalendar();
|
||
}
|
||
});
|
||
} catch (error) {
|
||
console.error('绑定导航事件出错:', error);
|
||
}
|
||
}
|
||
|
||
// 初始化日历
|
||
function initCalendar() {
|
||
try {
|
||
bindNavigationEvents();
|
||
renderCalendar();
|
||
} catch (error) {
|
||
console.error('初始化日历出错:', error);
|
||
}
|
||
}
|
||
|
||
// 当DOM加载完成后初始化
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', initCalendar);
|
||
} else {
|
||
initCalendar();
|
||
}
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html> |