223 lines
6.6 KiB
JavaScript
223 lines
6.6 KiB
JavaScript
#!/usr/bin/env node
|
||
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
const axios = require('axios');
|
||
require('dotenv').config({ path: path.join(__dirname, '../../../.env') });
|
||
|
||
// API配置
|
||
const API_BASE_URL = process.env.API_BASE_URL || 'https://api.qonnwolf.com/api/v1';
|
||
const AUTHORIZATION = process.env.AUTHORIZATION || '';
|
||
const TEACHER_NAME = process.env.EMPLOYEE_NAME || '橙子(程城)';
|
||
|
||
// 日期处理工具函数
|
||
function formatDate(date) {
|
||
const year = date.getFullYear();
|
||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||
const day = String(date.getDate()).padStart(2, '0');
|
||
return `${year}-${month}-${day}`;
|
||
}
|
||
|
||
function parseDate(dateStr) {
|
||
// 支持多种日期格式:2026-04-24、2026/04/24、20260424、04-24、4月24日等
|
||
dateStr = dateStr.replace(/年|月/g, '-').replace(/日/g, '');
|
||
|
||
// 如果是短日期,默认使用当前年份
|
||
if (/^\d{1,2}-\d{1,2}$/.test(dateStr)) {
|
||
const currentYear = new Date().getFullYear();
|
||
dateStr = `${currentYear}-${dateStr}`;
|
||
}
|
||
|
||
// 处理纯数字格式
|
||
if (/^\d{8}$/.test(dateStr)) {
|
||
dateStr = `${dateStr.slice(0, 4)}-${dateStr.slice(4, 6)}-${dateStr.slice(6, 8)}`;
|
||
}
|
||
|
||
// 替换斜杠为横杠
|
||
dateStr = dateStr.replace(/\//g, '-');
|
||
|
||
const date = new Date(dateStr);
|
||
if (isNaN(date.getTime())) {
|
||
throw new Error(`无效的日期格式:${dateStr},请使用YYYY-MM-DD格式`);
|
||
}
|
||
return date;
|
||
}
|
||
|
||
function getDateRange(startDateStr, endDateStr) {
|
||
const startDate = parseDate(startDateStr);
|
||
const endDate = endDateStr ? parseDate(endDateStr) : startDate;
|
||
|
||
if (startDate > endDate) {
|
||
throw new Error('开始日期不能晚于结束日期');
|
||
}
|
||
|
||
const dates = [];
|
||
const currentDate = new Date(startDate);
|
||
while (currentDate <= endDate) {
|
||
dates.push(formatDate(currentDate));
|
||
currentDate.setDate(currentDate.getDate() + 1);
|
||
}
|
||
return dates;
|
||
}
|
||
|
||
// 调用API获取单天数据
|
||
async function fetchSchedule(date) {
|
||
try {
|
||
console.log(`正在获取 ${date} 的教学日程数据...`);
|
||
const response = await axios.get(`${API_BASE_URL}/reports/teaching-schedule`, {
|
||
headers: {
|
||
'Authorization': AUTHORIZATION
|
||
},
|
||
params: {
|
||
teaching_date: date,
|
||
teacher_name: TEACHER_NAME
|
||
}
|
||
});
|
||
|
||
if (response.data.code !== 0) {
|
||
throw new Error(`API返回错误:${response.data.message}`);
|
||
}
|
||
|
||
const data = response.data.data;
|
||
return {
|
||
teaching_date: date,
|
||
items: data.items.map(item => ({
|
||
class_id: item.class_id,
|
||
class_name: item.class_name,
|
||
start_time: item.teaching_time_period.split('-')[0].trim(),
|
||
end_time: item.teaching_time_period.split('-')[1].trim(),
|
||
teacher_name: item.teacher_name,
|
||
classroom: item.school_name,
|
||
students: item.student_names.map(name => {
|
||
// 先默认都是出勤,后续可以根据实际出勤数据调整
|
||
return {
|
||
student_name: name,
|
||
attendance_status: '✅ 出勤',
|
||
remark: ''
|
||
};
|
||
})
|
||
}))
|
||
};
|
||
} catch (error) {
|
||
console.error(`获取 ${date} 数据失败:`, error.message);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
// 批量获取日期范围内的数据
|
||
async function fetchScheduleRange(dates) {
|
||
const scheduleData = [];
|
||
for (const date of dates) {
|
||
const data = await fetchSchedule(date);
|
||
scheduleData.push(data);
|
||
}
|
||
return scheduleData;
|
||
}
|
||
|
||
// 生成HTML文件
|
||
function generateHTML(scheduleData, startDate, endDate) {
|
||
// 读取模板文件
|
||
const templatePath = path.join(__dirname, 'template.html');
|
||
let template = fs.readFileSync(templatePath, 'utf-8');
|
||
|
||
// 生成日期范围显示文本
|
||
const dateRangeText = startDate === endDate ? startDate : `${startDate} 至 ${endDate}`;
|
||
const updateTime = formatDate(new Date()) + ' ' + new Date().toTimeString().slice(0, 5);
|
||
|
||
// 替换模板中的占位符
|
||
template = template.replace(/{{dateRange}}/g, dateRangeText);
|
||
template = template.replace(/{{updateTime}}/g, updateTime);
|
||
template = template.replace(/{{totalDays}}/g, scheduleData.length);
|
||
template = template.replace(/const scheduleData = {{scheduleData}};/, `const scheduleData = ${JSON.stringify(scheduleData, null, 2)};`);
|
||
|
||
// 确保输出目录存在
|
||
const outputDir = path.join(__dirname, `../../../output/teaching-schedule/${dateRangeText.replace(/ 至 /g, '_')}`);
|
||
if (!fs.existsSync(outputDir)) {
|
||
fs.mkdirSync(outputDir, { recursive: true });
|
||
}
|
||
|
||
// 写入HTML文件
|
||
const htmlPath = path.join(outputDir, 'schedule.html');
|
||
fs.writeFileSync(htmlPath, template, 'utf-8');
|
||
|
||
// 写入JSON数据文件
|
||
const jsonPath = path.join(outputDir, 'schedule.json');
|
||
fs.writeFileSync(jsonPath, JSON.stringify(scheduleData, null, 2), 'utf-8');
|
||
|
||
return {
|
||
htmlPath,
|
||
jsonPath,
|
||
outputDir,
|
||
dateRangeText
|
||
};
|
||
}
|
||
|
||
// 主函数
|
||
async function main() {
|
||
try {
|
||
// 解析命令行参数
|
||
const args = process.argv.slice(2);
|
||
let startDateStr, endDateStr;
|
||
|
||
if (args.length === 0) {
|
||
// 默认查询今天
|
||
const today = new Date();
|
||
startDateStr = formatDate(today);
|
||
endDateStr = startDateStr;
|
||
} else if (args.length === 1) {
|
||
// 查询单天
|
||
startDateStr = args[0];
|
||
endDateStr = startDateStr;
|
||
} else {
|
||
// 查询时间段
|
||
startDateStr = args[0];
|
||
endDateStr = args[1];
|
||
}
|
||
|
||
// 获取日期范围
|
||
const dates = getDateRange(startDateStr, endDateStr);
|
||
const startDate = dates[0];
|
||
const endDate = dates[dates.length - 1];
|
||
|
||
console.log(`查询日期范围:${startDate} 至 ${endDate}`);
|
||
console.log(`共 ${dates.length} 天`);
|
||
|
||
// 获取数据
|
||
const scheduleData = await fetchScheduleRange(dates);
|
||
|
||
// 统计信息
|
||
const totalClasses = scheduleData.reduce((sum, day) => sum + day.items.length, 0);
|
||
const totalStudents = scheduleData.reduce((sum, day) => {
|
||
return sum + day.items.reduce((daySum, cls) => daySum + cls.students.length, 0);
|
||
}, 0);
|
||
|
||
console.log(`查询完成:共 ${totalClasses} 节课,${totalStudents} 人次`);
|
||
|
||
// 生成HTML
|
||
const result = generateHTML(scheduleData, startDate, endDate);
|
||
|
||
console.log('');
|
||
console.log('✅ 教学日程生成成功!');
|
||
console.log('📁 输出目录:', result.outputDir);
|
||
console.log('📄 网页文件:', result.htmlPath);
|
||
console.log('📊 数据文件:', result.jsonPath);
|
||
console.log('');
|
||
console.log('直接打开schedule.html文件即可查看教学日程!');
|
||
|
||
} catch (error) {
|
||
console.error('❌ 生成失败:', error.message);
|
||
process.exit(1);
|
||
}
|
||
}
|
||
|
||
// 运行主函数
|
||
if (require.main === module) {
|
||
main();
|
||
}
|
||
|
||
module.exports = {
|
||
fetchSchedule,
|
||
fetchScheduleRange,
|
||
generateHTML
|
||
};
|