来源: 通义千问
效果图
代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>年度日历</title>
<style>
body {
font-family: Arial, sans-serif;
}
.calendar-container {
margin: 20px auto;
width: 90%;
max-width: 1000px;
}
h1,
h2 {
text-align: center;
color: #4a148c;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}
th,
td {
padding: 10px;
text-align: center;
border: 1px solid #ddd;
position: relative;
}
th {
background-color: #e0e0e0;
color: #4a148c;
}
.workday {
background-color: #ffffcc;
}
/* 浅黄色 */
.holiday,
.off-day {
background-color: white;
}
/* 默认白色 */
.makeup-workday {
background-color: #ffffcc;
}
/* 调休补班时为浅黄色 */
.special-date {
background-color: #6a1b9a;
color: white;
}
/* 紫色 */
.service-day {
border: 2px solid #42a5f5 !important;
}
/* 蓝色 */
.today {
background-color: #fff25d;
}
/* 当天日期为紫色边框 */
.month-separator {
border-top: 2px solid #4a148c;
margin: 20px 0;
}
.today-display {
text-align: center;
color: #4a148c;
margin-bottom: 20px;
}
.top-right-corner {
position: absolute;
top: 0;
right: 0;
background-color: #e3e3e3;
/* 确保文字背景与单元格背景一致 */
padding: 2px 5px;
/* 根据需要调整内边距 */
font-size: 0.8em;
/* 调整字体大小 */
}
</style>
</head>
<body>
<div class="calendar-container">
<div class="today-display" id="todayDisplay"></div>
<h1 id="yearTitle">2024年日历</h1>
<input type="number" id="yearInput" value="2024">
<button onclick="updateCalendar()">更新日历</button>
<div style="float: right;">
<table style="width: 300px;">
<tbody>
<tr>
<td class="workday" style="width: 100px;">工作日</td>
<td class="service-day workday" style="width: 100px;">服务日</td>
<td class="workday" style="width: 100px;">驻场'<span class="top-right-corner">上海</span>'</td>
</tr>
</tbody>
</table>
</div>
<div id="calendarContainer"></div>
</div>
<script>
// 法定节假日列表
const holidays = [
/// 2024年
'2024-01-01', // 元旦
'2024-02-10', '2024-02-11', '2024-02-12', '2024-02-13', '2024-02-14', '2024-02-15', '2024-02-16',
'2024-02-17', // 春节
'2024-04-04', '2024-04-05', '2024-04-06', // 清明节
'2024-05-01', '2024-05-02', '2024-05-03', '2024-05-04', '2024-05-05', // 劳动节
'2024-06-08', '2024-06-09', '2024-06-10', // 端午节
'2024-09-15', '2024-09-16', '2024-09-17', // 中秋节
'2024-10-01', '2024-10-02', '2024-10-03', '2024-10-04', '2024-10-05', '2024-10-06', '2024-10-07', // 国庆节
/// 2025年
'2025-01-01', // 元旦
'2025-01-28', '2025-01-29', '2025-01-30', '2024-01-31', '2025-02-02', '2025-02-03', '2025-02-04', // 春节
'2025-04-04', '2025-04-05', '2025-04-06', // 清明节
'2025-05-01', '2025-05-02', '2025-05-03', '2025-05-04', '2025-05-05', // 劳动节
'2025-05-31', '2024-06-01', '2024-06-02', // 端午节
'2025-10-01', '2025-10-02', '2025-10-03', '2025-10-04', '2025-10-05', '2025-10-06', '2025-10-07',
'2025-10-08', // 国庆节中秋节
];
// 调休补班列表()
const makeupDays = [
/// 2024年
'2024-02-04', '2024-02-18', // 春节调休补班
'2024-04-07', // 清明节调休补班
'2024-04-28', '2024-05-11', // 劳动节调休补班
'2024-09-14', // 中秋节调休补班
'2024-09-29', '2024-10-12', // 国庆节调休补班
/// 2025年
'2025-01-26', '2025-02-08', // 春节调休补班
'2025-04-27', // 劳动节调休补班
'2025-09-28', // 中秋节调休补班
'2025-10-11', // 国庆节调休补班
];
// 驻场的日期
const inSceneDates = [
// 2024
['2024-08-11', '2024-08-30'],
['2024-09-02', '2024-09-14'],
['2024-09-18', '2024-09-30'],
['2024-10-08', '2024-10-25'],
['2024-10-28', '2024-11-15'],
['2024-12-02', '2024-12-20'],
// 2025
['2025-01-06', '2025-01-17'],
['2025-02-17', '2025-03-07'],
['2025-03-24', '2025-04-03'],
['2025-04-21', '2025-04-30'],
['2025-05-19', '2025-05-30'],
['2025-06-16', '2025-07-04'],
['2025-07-21', '2025-08-08'],
]
const finalInSceneDates = flattenDateRanges(inSceneDates);
// 服务开始日期和天数
const serviceStartDate = '2024-08-12'; // 示例:服务从3月1日开始
const serviceWorkdaysCount = 7 * 30; // 示例:20个工作日
var serviceWorkdaysPassed = 0;
const serviceDays = []
function updateCalendar() {
const year = document.getElementById('yearInput').value;
document.getElementById('yearTitle').innerText = `${year}年日历`;
document.getElementById('calendarContainer').innerHTML = ''; // 清空旧日历
for (let month = 1; month <= 12; month++) {
if (month > 1) {
document.getElementById('calendarContainer').insertAdjacentHTML('beforeend',
'<hr class="month-separator">');
}
createMonthCalendar(year, month);
}
// 更新今天日期显示
const today = new Date();
document.getElementById('todayDisplay').textContent = `今天是:${today.toLocaleDateString()}`;
}
function createMonthCalendar(year, month) {
const container = document.getElementById('calendarContainer');
const table = document.createElement('table');
const thead = document.createElement('thead');
const tbody = document.createElement('tbody');
// Create header row with days of week
const headerRow = document.createElement('tr');
const daysOfWeek = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
daysOfWeek.forEach(day => {
const th = document.createElement('th');
th.textContent = day;
headerRow.appendChild(th);
});
thead.appendChild(headerRow);
table.appendChild(thead);
// Fill in calendar days
const date = new Date(year, month - 1, 1);
const lastDay = new Date(year, month, 0).getDate();
const startDay = date.getDay(); // Get the first day of the week (0=Sun, 1=Mon, ...)
let day = 1;
for (let i = 0;; i++) {
for (let j = 0; j < 7; j++) {
if (i === 0 && j < startDay || day > lastDay) {
} else {
const currentDate = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
const isHoliday = holidays.includes(currentDate);
const isMakeupDay = makeupDays.includes(currentDate);
const isWorkday = !isHoliday && ((j >= 1 && j <= 5) || isMakeupDay);
let isServiceDay = false
if (isWorkday) {
if (serviceDays.includes(currentDate)) {
isServiceDay = true
serviceDays.push(currentDate)
} else {
if (new Date(currentDate) >= new Date(serviceStartDate)) {
if (isWorkday) {
serviceWorkdaysPassed++;
if (serviceWorkdaysPassed <= serviceWorkdaysCount) {
isServiceDay = true
serviceDays.push(currentDate)
}
}
}
}
}
day++;
}
}
if (day > lastDay) break;
}
let endServiceDay = getMaxDate(serviceDays)
console.log(endServiceDay)
day = 1;
for (let i = 0;; i++) {
const row = document.createElement('tr');
for (let j = 0; j < 7; j++) {
if (i === 0 && j < startDay || day > lastDay) {
row.appendChild(document.createElement('td'));
} else {
const cell = document.createElement('td');
const currentDate = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
const isHoliday = holidays.includes(currentDate);
const isMakeupDay = makeupDays.includes(currentDate);
const isInSceneDay = finalInSceneDates.includes(currentDate);
const isWorkday = !isHoliday && ((j >= 1 && j <= 5) || isMakeupDay);
const today = new Date().toJSON().slice(0, 10) === currentDate;
let isServiceDay = false
if (isWorkday) {
cell.classList.add('workday');
// Check if this is a service workday
if (serviceDays.includes(currentDate)) {
isServiceDay = true
cell.classList.add('service-day');
} else {
if (new Date(currentDate) >= new Date(serviceStartDate)) {
if (isWorkday) {
serviceWorkdaysPassed++;
if (serviceWorkdaysPassed <= serviceWorkdaysCount) {
isServiceDay = true
cell.classList.add('service-day');
serviceDays.push(currentDate)
}
}
}
}
} else {
cell.classList.add('holiday');
}
let remake = ''
if (isInSceneDay) {
if (endServiceDay != null && new Date(currentDate) <= new Date(endServiceDay)) {
remake += '<span class="top-right-corner">上海</span>'
}
}
if (today) {
cell.classList.add('today'); // Add purple border to today's date
}
cell.innerHTML = day + remake;
day++;
row.appendChild(cell);
}
}
tbody.appendChild(row);
if (day > lastDay) break;
}
table.appendChild(tbody);
// Add month title
const monthTitle = document.createElement('h2');
const monthNames = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'];
monthTitle.textContent = monthNames[month - 1];
container.appendChild(monthTitle);
container.appendChild(table);
}
// Initialize the calendar on page load
window.onload = function() {
updateCalendar();
};
function generateDateRange(startDate, endDate) {
const dateArray = [];
let currentDate = new Date(startDate);
const end = new Date(endDate);
while (currentDate <= end) {
dateArray.push(currentDate.toISOString().split('T')[0]);
currentDate.setDate(currentDate.getDate() + 1);
}
return dateArray;
}
function flattenDateRanges(dateRanges) {
return dateRanges.reduce((acc, [start, end]) => {
acc.push(...generateDateRange(start, end));
return acc;
}, []);
}
function getMaxDate(dateArray) {
if (dateArray.length === 0) return null;
// 将日期字符串数组映射为时间戳数组,并找到最大值
const maxTimestamp = Math.max(...dateArray.map(dateStr => Date.parse(dateStr)));
// 将最大时间戳转换回日期字符串
const maxDate = new Date(maxTimestamp).toISOString().split('T')[0];
return maxDate;
}
</script>
</body>
</html>