/** * 解析周次 */ function parseWeeks(weekStr) { if (!weekStr) return []; let parts = String(weekStr).split(','); let weeks = new Set(); for (let p of parts) { let num = parseInt(p.trim()); if (!isNaN(num)) weeks.add(num); } return Array.from(weeks).sort((a, b) => a - b); } async function runImportFlow() { try { if (typeof window.AndroidBridge !== 'undefined') { AndroidBridge.showToast("正在获取作息时间与学期列表..."); } else { console.log("【1/4】正在请求 week.page 获取学期和作息时间..."); } // 1. 获取学期列表与作息时间 const pageRes = await fetch('/new/student/xsgrkb/week.page', { method: 'GET' }); const pageHtml = await pageRes.text(); const parser = new DOMParser(); const doc = parser.parseFromString(pageHtml, 'text/html'); const selectElem = doc.getElementById('xnxqdm'); let semesters = [], semesterValues = [], 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("未找到学期列表。"); // 提取作息时间,并分离 1-12 节(常规) 和 13-14 节(中午异形) let rawTimeMap = {}; let standardTimeSlots = []; const bhMatch = pageHtml.match(/var\s+businessHours\s*=\s*\$\.parseJSON\('(\[.*?\])'\);/); if (bhMatch && bhMatch[1]) { const bhData = JSON.parse(bhMatch[1]); bhData.forEach(item => { let num = parseInt(item.jcdm, 10); let st = item.qssj.substring(0, 5); let et = item.jssj.substring(0, 5); rawTimeMap[num] = { start: st, end: et }; // 记录所有节次的真实时间 // 只有 1-12 节作为正常的网格标尺 if (num >= 1 && num <= 12) { standardTimeSlots.push({ number: num, startTime: st, endTime: et }); } }); standardTimeSlots.sort((a, b) => a.number - b.number); } else { throw new Error("未抓取到作息时间!"); } // 2. 选择学期 let selectedIdx = defaultIndex; if (typeof window.AndroidBridgePromise !== 'undefined') { let userChoice = await window.AndroidBridgePromise.showSingleSelection( "请选择要导入的学期", JSON.stringify(semesters), defaultIndex ); if (userChoice === null) { AndroidBridge.showToast("已取消导入"); return; } selectedIdx = userChoice; } else { let msg = "【浏览器测试】请选择学期序号:\n\n"; semesters.forEach((s, idx) => msg += `[${idx}] : ${s}\n`); let userInput = prompt(msg, defaultIndex); if (userInput === null) return; selectedIdx = parseInt(userInput); if (isNaN(selectedIdx)) selectedIdx = defaultIndex; } const targetXnxqdm = semesterValues[selectedIdx]; if (typeof window.AndroidBridge !== 'undefined') { AndroidBridge.showToast(`正在获取 [${semesters[selectedIdx]}] 数据...`); } // 3. 请求课表接口 let formData = new URLSearchParams(); formData.append('xnxqdm', targetXnxqdm); formData.append('zc', ''); formData.append('d1', '2020-01-01 00:00:00'); formData.append('d2', '2030-01-01 00:00:00'); const apiRes = await fetch('/new/student/xsgrkb/getCalendarWeekDatas', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'X-Requested-With': 'XMLHttpRequest' }, body: formData.toString() }); const apiJson = await apiRes.json(); if (apiJson.code !== 0 || !apiJson.data) throw new Error("获取课表失败"); if (apiJson.data.length === 0) { const errMsg = "该学期暂无排课数据。"; if (typeof window.AndroidBridgePromise !== 'undefined') { await window.AndroidBridgePromise.showAlert("提示", errMsg, "好的"); } else alert(errMsg); return; } // 4. 数据转换与倒挂课表隔离 let parsedCourses = []; apiJson.data.forEach(item => { let courseObj = { name: item.kcmc || "未知课程", teacher: item.teaxms || "未知", position: item.jxcdmc || "待定", day: parseInt(item.xq), isCustomTime: false }; courseObj.weeks = parseWeeks(item.zc); let startSec = parseInt(item.ps); let endSec = parseInt(item.pe); // 【核心修正】处理第13、14节的中午倒挂课程 if (startSec > 12 || endSec > 12) { courseObj.isCustomTime = true; // 取教务系统真实设定的时间(如 11:45) courseObj.customStartTime = rawTimeMap[startSec] ? rawTimeMap[startSec].start : "11:45"; courseObj.customEndTime = rawTimeMap[endSec] ? rawTimeMap[endSec].end : "13:15"; } else { courseObj.startSection = startSec; courseObj.endSection = endSec; } if (courseObj.name && !isNaN(courseObj.day) && courseObj.weeks.length > 0) { parsedCourses.push(courseObj); } }); // 去重逻辑 let uniqueCourses = []; let courseSet = new Set(); parsedCourses.forEach(course => { let uniqueKey = course.isCustomTime ? `${course.day}-${course.customStartTime}-${course.customEndTime}-${course.name}-${course.weeks.join(',')}` : `${course.day}-${course.startSection}-${course.endSection}-${course.name}-${course.weeks.join(',')}`; if (!courseSet.has(uniqueKey)) { courseSet.add(uniqueKey); uniqueCourses.push(course); } }); const config = { "defaultClassDuration": 45, "defaultBreakDuration": 10 }; // 浏览器测试输出 if (typeof window.AndroidBridgePromise === 'undefined') { console.log("【修正后的正常网格时间】", standardTimeSlots); console.log(`【提取的课程 (${uniqueCourses.length}门)】\n`, JSON.stringify(uniqueCourses, null, 2)); alert("解析成功!已将中午课程转为无缝自定义时间。请看F12。"); return; } // 5. 保存到APP await window.AndroidBridgePromise.saveCourseConfig(JSON.stringify(config)); await window.AndroidBridgePromise.savePresetTimeSlots(JSON.stringify(standardTimeSlots)); const saveResult = await window.AndroidBridgePromise.saveImportedCourses(JSON.stringify(uniqueCourses)); if (!saveResult) { AndroidBridge.showToast("保存失败,请重试!"); return; } AndroidBridge.showToast(`成功导入 ${uniqueCourses.length} 节课程!`); AndroidBridge.notifyTaskCompletion(); } catch (error) { if (typeof window.AndroidBridge !== 'undefined') AndroidBridge.showToast("异常: " + error.message); else alert("异常: " + error.message); } } runImportFlow();