Files
ClassFeedback/.claude/skills/教学日程查询/index.js

223 lines
6.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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
};