/**
* 呼和浩特民族学院 (IMNC) 课表解析脚本-通过 WebVPN 登录
* 放置于测试目录用于真机测试
*/
// 周次解析函数
function parseWeeks(weekStr) {
let weeks = [];
if (!weekStr) return weeks;
let isSingle = weekStr.includes('单');
let isDouble = weekStr.includes('双');
// 匹配 "1-16", "第1-9周"
let match = weekStr.match(/(\d+)-(\d+)/);
if (match) {
let start = parseInt(match[1]);
let end = parseInt(match[2]);
for (let i = start; i <= end; i++) {
if (isSingle && i % 2 === 0) continue;
if (isDouble && i % 2 !== 0) continue;
weeks.push(i);
}
} else {
// 匹配 "第13周"
let singleMatch = weekStr.match(/(\d+)/);
if (singleMatch) {
weeks.push(parseInt(singleMatch[1]));
}
}
return weeks;
}
// 核心解析函数
function fetchAndParseCourses() {
let courses = [];
let table = document.querySelector('#timetable');
if (!table) return null;
let rows = table.querySelectorAll('tr');
// 第 0 行是表头,从第 1 行开始遍历节次
for (let i = 1; i < rows.length; i++) {
let row = rows[i];
let cells = row.querySelectorAll('td');
let section = i; // 1 到 13 节
for (let j = 0; j < cells.length; j++) {
let cell = cells[j];
let day = j + 1; // 星期 1 到 7
let html = cell.innerHTML.trim();
if (!html || html === ' ') continue;
// 按
分割
let parts = html.split(/
/i).map(s => s.trim()).filter(s => s !== '');
// 每 5 个元素代表一个完整的课程块
for (let k = 0; k < parts.length; k += 5) {
if (k + 3 >= parts.length) break;
let namePart = parts[k];
let position = parts[k+1];
let teacher = parts[k+2];
let weekStr = parts[k+3];
// parts[k+4] 是 "讲授" 等类型,暂时不需要存入
// 提取书名号内的课程名
let nameMatch = namePart.match(/<<(.*?)>>/);
let name = nameMatch ? nameMatch[1] : namePart;
// 兼容某些浏览器可能将转义符还原的情况
if (!nameMatch) {
let nameMatch2 = namePart.match(/<<(.*?)>>/);
if (nameMatch2) name = nameMatch2[1];
}
let weeks = parseWeeks(weekStr);
// 查找同一天、同名、同老师、同地点、同周次,且正好是上一节的课程(合并连上的课)
let existingCourse = courses.find(c =>
c.name === name &&
c.day === day &&
c.teacher === teacher &&
c.position === position &&
JSON.stringify(c.weeks) === JSON.stringify(weeks) &&
c.endSection === section - 1
);
if (existingCourse) {
existingCourse.endSection = section;
} else {
courses.push({
name: name,
teacher: teacher,
position: position,
day: day,
startSection: section,
endSection: section,
weeks: weeks
});
}
}
}
}
return courses;
}
function cleanCellText(cell) {
return cell.textContent.replace(/\u00a0/g, ' ').replace(/\s+/g, ' ').trim();
}
function parseNoArrangementCourses() {
let table = document.querySelector('#noArrangement');
if (!table) return [];
let rows = table.querySelectorAll('tr');
let courses = [];
let seen = {};
for (let i = 1; i < rows.length; i++) {
let cells = rows[i].querySelectorAll('td');
if (cells.length < 8) continue;
let course = {
courseId: cleanCellText(cells[0]),
name: cleanCellText(cells[1]),
sequence: cleanCellText(cells[2]),
teacher: cleanCellText(cells[3]) || '未填写教师',
combinedClass: cleanCellText(cells[4]),
weeks: cleanCellText(cells[5]),
day: cleanCellText(cells[6]),
position: cleanCellText(cells[7])
};
if (!course.courseId && !course.name) continue;
let key = [course.courseId, course.name, course.sequence, course.teacher, course.combinedClass, course.weeks, course.day, course.position].join('|');
if (seen[key]) continue;
seen[key] = true;
courses.push(course);
}
return courses;
}
function formatNoArrangementMessage(courses) {
let lines = courses.map((course, index) => {
let teacher = course.teacher || '未填写教师';
let weeks = course.weeks || '未填写周次';
return `${index + 1}. ${course.name} / ${teacher} / ${weeks}`;
});
return `检测到 ${courses.length} 门课程没有具体上课时间或地点,无法自动放入课表:\n\n${lines.join('\n')}\n\n请在确认课程时间后重新导入,点击【继续】将导入已知课程。`;
}
// 调度流程
async function runImportFlow() {
try {
AndroidBridge.showToast("开始解析课表...");
const alertConfirmed = await window.AndroidBridgePromise.showAlert(
"导入确认",
"请确保您目前处于教务系统的“学生课表”显示页面。\n是否立即提取并导入课表?",
"开始提取"
);
if (!alertConfirmed) {
AndroidBridge.showToast("导入已取消");
return;
}
let courses = fetchAndParseCourses();
if (!courses || courses.length === 0) {
await window.AndroidBridgePromise.showAlert("错误", "未在当前页面找到课表数据,请确认是否处于课表页面,或联系适配开发者。", "好的");
return;
}
let noArrangementCourses = parseNoArrangementCourses();
if (noArrangementCourses.length > 0) {
await window.AndroidBridgePromise.showAlert(
"存在未安排课程",
formatNoArrangementMessage(noArrangementCourses),
"继续"
);
}
await window.AndroidBridgePromise.saveImportedCourses(JSON.stringify(courses));
AndroidBridge.showToast(`成功导入 ${courses.length} 门课程块!`);
AndroidBridge.notifyTaskCompletion();
} catch (error) {
AndroidBridge.showToast("导入发生错误: " + error.message);
}
}
// 启动执行
runImportFlow();