| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- // 济宁医学院教务(乘方教务 · 旧版 .action 接口)适配器
- const PRESET_TIME_SLOTS = [
- { number: 1, startTime: "08:00", endTime: "08:40" },
- { number: 2, startTime: "08:50", endTime: "09:30" },
- { number: 3, startTime: "09:50", endTime: "10:30" },
- { number: 4, startTime: "10:40", endTime: "11:20" },
- { number: 5, startTime: "11:30", endTime: "12:10" },
- { number: 6, startTime: "14:30", endTime: "15:10" },
- { number: 7, startTime: "15:20", endTime: "16:00" },
- { number: 8, startTime: "16:20", endTime: "17:00" },
- { number: 9, startTime: "17:10", endTime: "17:50" },
- { number: 10, startTime: "18:00", endTime: "18:40" },
- { number: 11, startTime: "19:30", endTime: "20:10" },
- { number: 12, startTime: "20:20", endTime: "21:00" }
- ];
- // 周次字符串 "10,7,8,9" → 去重排序的周数组
- function parseWeeks(weekStr) {
- if (!weekStr) return [];
- const weeks = weekStr.split(",").map(w => parseInt(w.trim(), 10)).filter(w => !isNaN(w) && w > 0);
- return [...new Set(weeks)].sort((a, b) => a - b);
- }
- // 教室可能为空、含 "\\" 分隔的多教室(如 "B205\206教室")或以 "," 分隔的多场地
- function resolvePosition(raw) {
- const position = String(raw || "").replace(/\\/g, "/").trim();
- return position || "待定";
- }
- // kbxx 课程 JSON → 拾光课程格式(合并同 key 课程的周次)
- function parseCourseList(kbxx) {
- if (!Array.isArray(kbxx)) throw new Error("课表接口返回格式不正确");
- const courseMap = new Map();
- kbxx.forEach(item => {
- const day = parseInt(item.xq, 10);
- const sections = String(item.jcdm2 || "").split(",")
- .map(s => parseInt(s.trim(), 10)).filter(s => !isNaN(s));
- const allWeeks = parseWeeks(item.zcs);
- if (!item.kcmc || sections.length === 0 || allWeeks.length === 0 || isNaN(day) || day < 1 || day > 7) return;
- const course = {
- name: item.kcmc.trim(),
- teacher: String(item.teaxms || "").trim() || "未知",
- position: resolvePosition(item.jxcdmcs),
- day,
- startSection: Math.min(...sections),
- endSection: Math.max(...sections),
- weeks: allWeeks
- };
- const key = [course.name, course.teacher, course.position, course.day,
- course.startSection, course.endSection].join("__");
- const existing = courseMap.get(key);
- if (existing) existing.weeks = [...new Set([...existing.weeks, ...course.weeks])].sort((a, b) => a - b);
- else courseMap.set(key, course);
- });
- return Array.from(courseMap.values()).sort((a, b) =>
- a.day - b.day || a.startSection - b.startSection || a.endSection - b.endSection || a.name.localeCompare(b.name)
- );
- }
- // 读取课表页中的学期下拉框
- function extractSemesterOptions(doc) {
- const selectElem = doc.getElementById("xnxqdm");
- if (!selectElem) return null;
- const semesters = [];
- const semesterValues = [];
- let defaultIndex = 0;
- Array.from(selectElem.querySelectorAll("option")).forEach(option => {
- if (!option.value) return;
- semesters.push(option.innerText.trim());
- semesterValues.push(option.value);
- if (option.selected || option.hasAttribute("selected")) defaultIndex = semesters.length - 1;
- });
- if (semesters.length === 0) return null;
- const start = Math.max(0, defaultIndex - 1);
- const end = Math.min(semesters.length, defaultIndex + 10);
- return {
- semesters: semesters.slice(start, end),
- semesterValues: semesterValues.slice(start, end),
- defaultIndex: defaultIndex - start
- };
- }
- // 导入前提示先登录教务系统
- async function promptUserToStart() {
- return await window.shiguangBridgePromise.showAlert(
- "济宁医学院教务导入",
- "请先确保已登录教务系统,再继续导入。",
- "我已登录"
- );
- }
- // 选择学期
- async function selectSemester(semesterOptions) {
- const selectedIndex = await window.shiguangBridgePromise.showSingleSelection(
- "选择学期",
- JSON.stringify(semesterOptions.semesters),
- semesterOptions.defaultIndex
- );
- if (selectedIndex === null || selectedIndex < 0) return null;
- return {
- label: semesterOptions.semesters[selectedIndex],
- value: semesterOptions.semesterValues[selectedIndex]
- };
- }
- // 拉取课表页 HTML(含学期列表)
- async function fetchSchedulePage() {
- const response = await fetch("/xsgrkbcx!getXsgrbkList.action", { method: "GET", credentials: "include" });
- if (!response.ok) throw new Error(`无法打开课表页面(HTTP ${response.status})`);
- return response.text();
- }
- // 拉取指定学期课表(HTML 内嵌 var kbxx=[...])
- async function fetchCourseData(xnxqdm) {
- const response = await fetch(
- `/xsgrkbcx!xsAllKbList.action?xnxqdm=${encodeURIComponent(xnxqdm)}`,
- { method: "GET", credentials: "include" }
- );
- if (!response.ok) throw new Error(`课表请求失败(HTTP ${response.status})`);
- const htmlText = await response.text();
- const match = htmlText.match(/var\s+kbxx\s*=\s*(\[[\s\S]*?\]);/);
- if (!match) throw new Error("课表数据解析失败,请检查登录状态");
- let kbxx;
- try {
- kbxx = JSON.parse(match[1]);
- } catch (error) {
- throw new Error(`课表数据解析失败:${error.message}`);
- }
- return kbxx;
- }
- // 主流程:提示 → 选学期 → 拉课表 → 保存课程与作息
- async function runImportFlow() {
- try {
- const confirmed = await promptUserToStart();
- if (!confirmed) { window.shiguangBridge.showToast("导入已取消"); return; }
- const pageHtml = await fetchSchedulePage();
- const semesterOptions = extractSemesterOptions(new DOMParser().parseFromString(pageHtml, "text/html"));
- if (!semesterOptions) throw new Error("未找到学期列表,请先登录教务系统");
- const semester = await selectSemester(semesterOptions);
- if (!semester) { window.shiguangBridge.showToast("导入已取消"); return; }
- window.shiguangBridge.showToast(`正在获取 ${semester.label} 的课表...`);
- const courses = parseCourseList(await fetchCourseData(semester.value));
- if (courses.length === 0) {
- await window.shiguangBridgePromise.showAlert(
- "提示",
- "该学期没有获取到课程数据,请检查登录状态和所选学期。",
- "确定"
- );
- return;
- }
- await window.shiguangBridgePromise.saveImportedCourses(JSON.stringify(courses));
- try {
- await window.shiguangBridgePromise.savePresetTimeSlots(JSON.stringify(PRESET_TIME_SLOTS));
- } catch (error) {
- window.shiguangBridge.showToast(`课程已导入,作息时间导入失败:${error.message}`);
- }
- window.shiguangBridge.showToast(`成功导入 ${courses.length} 门课程!`);
- window.shiguangBridge.notifyTaskCompletion();
- } catch (error) {
- await window.shiguangBridgePromise.showAlert(
- "导入失败",
- error.message || String(error),
- "确定"
- );
- }
- }
- runImportFlow();
|