/** * 解析周次字符串 (例如 "17,2,3,4,6") */ function parseWeeks(weekStr) { if (!weekStr) return []; let weeks = []; let parts = String(weekStr).split(','); for (let part of parts) { if (part.includes('-')) { let [start, end] = part.split('-'); for (let i = parseInt(start); i <= parseInt(end); i++) { if (!weeks.includes(i)) weeks.push(i); } } else { let w = parseInt(part.trim()); if (!isNaN(w) && !weeks.includes(w)) weeks.push(w); } } return weeks.sort((a, b) => a - b); } /** * 直接从 JS 变量中提取 JSON 数据 */ function extractCoursesFromHtml(htmlText) { let parsedCourses = []; // 使用正则表达式精准捕获 var kbxx = [...] 中的 JSON 数组 let match = htmlText.match(/var\s+kbxx\s*=\s*(\[[\s\S]*?\])\s*;/); if (!match || !match[1]) { if (htmlText.includes(' { let courseObj = { name: item.kcmc || "未知课程", teacher: item.teaxms || "未知", position: item.jxcdmcs || "待定", day: parseInt(item.xq), isCustomTime: false }; // 处理周次 (item.zcs 格式为 "18,2,3,4,7,8") if (item.zcs) { courseObj.weeks = parseWeeks(item.zcs); } else { return; // 无周次则抛弃 } // 处理节次 (item.jcdm2 格式为 "05,06" 或 "10") if (item.jcdm2) { let sections = item.jcdm2.split(',').map(s => parseInt(s, 10)); courseObj.startSection = sections[0]; courseObj.endSection = sections[sections.length - 1]; } else { return; // 无节次则抛弃 } // 只有包含完整有效信息才加入 if (courseObj.name && courseObj.weeks && courseObj.weeks.length > 0) { parsedCourses.push(courseObj); } }); // 去重逻辑 let uniqueCourses = []; let courseSet = new Set(); parsedCourses.forEach(course => { let uniqueKey = `${course.day}-${course.startSection}-${course.endSection}-${course.name}-${course.weeks.join(',')}`; if (!courseSet.has(uniqueKey)) { courseSet.add(uniqueKey); uniqueCourses.push(course); } }); return uniqueCourses; } /** * 生成学校专属的作息时间段 */ function getPresetTimeSlots() { return [ { "number": 1, "startTime": "08:00", "endTime": "08:45" }, // 课间 10分 { "number": 2, "startTime": "08:55", "endTime": "09:40" }, // 课间 20分 (特殊) { "number": 3, "startTime": "10:00", "endTime": "10:45" }, // 课间 10分 { "number": 4, "startTime": "10:55", "endTime": "11:40" }, { "number": 5, "startTime": "14:00", "endTime": "14:45" }, // 课间 10分 { "number": 6, "startTime": "14:55", "endTime": "15:40" }, // 课间 15分 (特殊) { "number": 7, "startTime": "15:55", "endTime": "16:40" }, // 课间 10分 { "number": 8, "startTime": "16:50", "endTime": "17:35" }, { "number": 9, "startTime": "19:00", "endTime": "19:45" }, // 课间 10分 { "number": 10, "startTime": "19:55", "endTime": "20:40" }, // 课间 10分 { "number": 11, "startTime": "20:50", "endTime": "21:35" } ]; } /** * 生成全局课表配置 */ function getCourseConfig() { return { "defaultClassDuration": 45, // 单节课 45 分钟 "defaultBreakDuration": 10 // 默认课间 10 分钟 }; } /** * 异步编排流程 */ async function runImportFlow() { try { if (typeof window.AndroidBridge !== 'undefined') { AndroidBridge.showToast("正在获取课表配置,请稍候..."); } else { console.log("正在请求获取学期列表..."); } // 第 1 步:请求外层页面,获取学期列表 const listResponse = await fetch('/xsgrkbcx!getXsgrbkList.action', { method: 'GET' }); const listHtml = await listResponse.text(); const parser = new DOMParser(); const listDoc = parser.parseFromString(listHtml, 'text/html'); const selectElem = listDoc.getElementById('xnxqdm'); let semesters = []; let semesterValues = []; let defaultIndex = 0; if (selectElem) { const options = selectElem.querySelectorAll('option'); options.forEach((opt, index) => { semesters.push(opt.innerText.trim()); semesterValues.push(opt.value); if (opt.hasAttribute('selected') || opt.selected) { defaultIndex = index; } }); } if (semesters.length === 0) { throw new Error("无法在页面中找到学期选项(xnxqdm),请确认教务系统是否正常。"); } // 第 2 步:选择学期 let selectedIdx = defaultIndex; if (typeof window.AndroidBridgePromise !== 'undefined') { // APP 内原生弹窗 let userChoice = await window.AndroidBridgePromise.showSingleSelection( "请选择要导入的学期", JSON.stringify(semesters), defaultIndex ); if (userChoice === null) { AndroidBridge.showToast("已取消导入"); return; } selectedIdx = userChoice; } else { // 电脑浏览器端原生 prompt 弹窗测试 let msg = "【浏览器测试】请选择学期对应的序号:\n\n"; semesters.forEach((s, idx) => { msg += `[ ${idx} ] : ${s}\n`; }); let userInput = prompt(msg, defaultIndex); if (userInput === null) { console.log("已取消测试。"); return; } selectedIdx = parseInt(userInput); if (isNaN(selectedIdx) || selectedIdx < 0 || selectedIdx >= semesters.length) { alert("输入的序号不合法,将使用默认学期!"); selectedIdx = defaultIndex; } } let targetXnxqdm = semesterValues[selectedIdx]; if (typeof window.AndroidBridge !== 'undefined') { AndroidBridge.showToast(`正在获取 [${semesters[selectedIdx]}] 课表数据...`); } else { console.log(`准备拉取学期 [${semesters[selectedIdx]} / 代码: ${targetXnxqdm}] 的课表数据...`); } // 第 3 步:带上学期参数,请求真正的课表数据接口 const kbResponse = await fetch(`/xsgrkbcx!xsAllKbList.action?xnxqdm=${targetXnxqdm}`, { method: 'GET' }); const kbHtmlText = await kbResponse.text(); // 第 4 步:提取数据 const courses = extractCoursesFromHtml(kbHtmlText); if (courses.length === 0) { const errMsg = "该学期暂无排课数据。"; if (typeof window.AndroidBridgePromise !== 'undefined') { await window.AndroidBridgePromise.showAlert("提示", errMsg, "好的"); } else { alert(errMsg); } return; } const config = getCourseConfig(); const timeSlots = getPresetTimeSlots(); // 浏览器测试环境,直接打印输出 if (typeof window.AndroidBridgePromise === 'undefined') { console.log("【测试成功】课表配置:", config); console.log("【测试成功】作息时间:", timeSlots); console.log("【测试成功】课程数据:\n", JSON.stringify(courses, null, 2)); alert(`解析成功!获取到 ${courses.length} 门课程以及专属作息。\n(请打开 F12 Console 控制台查看具体数据)`); return; } // APP 环境保存数据 await window.AndroidBridgePromise.saveCourseConfig(JSON.stringify(config)); await window.AndroidBridgePromise.savePresetTimeSlots(JSON.stringify(timeSlots)); const saveResult = await window.AndroidBridgePromise.saveImportedCourses(JSON.stringify(courses)); if (!saveResult) { AndroidBridge.showToast("保存课程失败,请重试!"); return; } AndroidBridge.showToast(`成功导入 ${courses.length} 节课程及作息时间!`); AndroidBridge.notifyTaskCompletion(); } catch (error) { if (typeof window.AndroidBridge !== 'undefined') { AndroidBridge.showToast("导入发生异常: " + error.message); } else { console.error("【导入发生异常】", error); alert("导入发生异常: " + error.message); } } } // 启动导入流程 runImportFlow();