Kaynağa Gözat

添加河南职业技术学院的课程导入配置及相关工具函数

YIKE 1 ay önce
ebeveyn
işleme
2a7e0788f5
2 değiştirilmiş dosya ile 221 ekleme ve 0 silme
  1. 9 0
      schools.json
  2. 212 0
      schools/hnzy.js

+ 9 - 0
schools.json

@@ -34,5 +34,14 @@
     "assetJsPath" : "schools/ynufe.js",
     "maintainer": "AxelPLN",
     "category": "BACHELOR_AND_ASSOCIATE"
+  },
+    {
+    "id": "school_hnzy",
+    "name": "河南职业技术学院",
+    "initial": "H",
+    "importUrl": "https://one.hnzj.edu.cn/common-service/kcb-pc/personage/personage",
+    "assetJsPath" : "schools/hnzy.js",
+    "maintainer": "一颗",
+    "category": "BACHELOR_AND_ASSOCIATE"
   }
 ]

+ 212 - 0
schools/hnzy.js

@@ -0,0 +1,212 @@
+// ====================== 工具函数 ======================
+
+// 展开 weeks 字符串 -> 数字数组
+function parseWeeks(weeksStr) {
+    const weeks = new Set();
+    if (!weeksStr) return [];
+    const parts = weeksStr.split(",");
+    for (const part of parts) {
+        if (part.includes("-")) {
+            const [start, end] = part.split("-").map(n => parseInt(n));
+            for (let i = start; i <= end && i <= 20; i++) {
+                weeks.add(i);
+            }
+        } else {
+            const n = parseInt(part);
+            if (n >= 1 && n <= 20) weeks.add(n);
+        }
+    }
+    return Array.from(weeks).sort((a, b) => a - b);
+}
+
+// 合并重复课程
+function mergeDuplicateCourses(courses) {
+    const merged = [];
+    const keyMap = {}; // key = name+day+startSection+endSection+position
+
+    for (const c of courses) {
+        const key = `${c.name}|${c.day}|${c.startSection}|${c.endSection}|${c.position}`;
+        if (!keyMap[key]) {
+            keyMap[key] = { ...c, weeks: [...c.weeks] };
+        } else {
+            keyMap[key].weeks = Array.from(new Set([...keyMap[key].weeks, ...c.weeks]));
+        }
+    }
+
+    for (const k in keyMap) merged.push(keyMap[k]);
+    return merged;
+}
+
+// ====================== 弹窗选择学年学期 ======================
+async function selectYearAndTerm(schoolYears, schoolTerms) {
+    try {
+        // 构造所有学年 x 学期组合
+        const options = [];
+        const mapping = []; // 用于根据选项索引找到学年和学期
+        schoolYears.forEach(y => {
+            schoolTerms.forEach(t => {
+                options.push(`${y.label} ${t.label}`);
+                mapping.push({ year: y.value, term: t.value });
+            });
+        });
+
+        const selectedIndex = await window.AndroidBridgePromise.showSingleSelection(
+            "请选择学年和学期",
+            JSON.stringify(options),
+            0
+        );
+
+        if (selectedIndex === null) return null;
+
+        return mapping[selectedIndex];
+    } catch (err) {
+        console.error("选择学年学期失败:", err);
+        return null;
+    }
+}
+
+
+// ====================== 异步获取学年学期 ======================
+async function fetchSchoolYearTerms() {
+    try {
+        const res = await fetch("https://one.hnzj.edu.cn/kcb/api/schoolyearTerms");
+        const json = await res.json();
+        return {
+            schoolYears: json.response.schoolYears,
+            schoolTerms: json.response.schoolTerms
+        };
+    } catch (err) {
+        console.error("获取学年学期失败:", err);
+        AndroidBridge.showToast("获取学年学期失败:" + err.message);
+        return null;
+    }
+}
+
+// ====================== 异步获取课程并处理 ======================
+async function fetchCoursesForAllWeeks(year, term) {
+    let allCourses = [];
+
+    for (let week = 1; week <= 20; week++) {
+        try {
+            const url = `https://one.hnzj.edu.cn/kcb/api/course?schoolYear=${year}&schoolTerm=${term}&week=${week}`;
+            const res = await fetch(url);
+            const json = await res.json();
+
+
+            json.response.forEach(dayInfo => {
+                dayInfo.data.forEach(c => {
+                    const weeks = parseWeeks(c.weeks);
+                    if (!weeks.length) return;
+                    allCourses.push({
+                        name: c.courseName,
+                        teacher: c.teacherName,
+                        position: c.classRoom,
+                        day: dayInfo.week,
+                        startSection: parseInt(c.startSection),
+                        endSection: parseInt(c.endSection),
+                        weeks
+                    });
+                });
+            });
+        } catch (err) {
+            console.error(`第 ${week} 周课程获取失败:`, err);
+        }
+    }
+
+    const mergedCourses = mergeDuplicateCourses(allCourses);
+
+
+    return mergedCourses.length ? mergedCourses : null;
+}
+
+// ====================== 保存课程 ======================
+async function saveCourses(courses) {
+    try {
+        const result = await window.AndroidBridgePromise.saveImportedCourses(JSON.stringify(courses));
+        if (result === true) {
+            AndroidBridge.showToast("课程导入成功!");
+            return true;
+        } else {
+            AndroidBridge.showToast("课程导入失败,请查看日志!");
+            return false;
+        }
+    } catch (err) {
+        console.error("保存课程失败:", err);
+        AndroidBridge.showToast("保存课程失败:" + err.message);
+        return false;
+    }
+}
+
+// ====================== 导入预设时间段 ======================
+// ====================== 导入预设时间段(实际大节时间) ======================
+async function importPresetTimeSlots() {
+    // 实际课程大节时间
+    const presetTimeSlots = [
+        { number: 1, startTime: "08:30", endTime: "10:00" }, // 第一大节(1-2)
+        { number: 2, startTime: "08:30", endTime: "10:00" }, // 第二节 1-2 合并
+        { number: 3, startTime: "10:20", endTime: "11:50" }, // 第三节(3-4)
+        { number: 4, startTime: "10:20", endTime: "11:50" }, // 第四节 3-4 合并
+        { number: 5, startTime: "14:20", endTime: "15:50" }, // 第五节(5-6)
+        { number: 6, startTime: "14:20", endTime: "15:50" }, // 第六节 5-6 合并
+        { number: 7, startTime: "16:10", endTime: "17:40" }, // 第七节(7-8)
+        { number: 8, startTime: "16:10", endTime: "17:40" }, // 第八节 7-8 合并
+        { number: 11, startTime: "19:00", endTime: "20:30" }, // 第十一节(11-12)
+        { number: 12, startTime: "19:00", endTime: "20:30" }  // 第十二节 11-12 合并
+    ];
+
+    try {
+        const result = await window.AndroidBridgePromise.savePresetTimeSlots(JSON.stringify(presetTimeSlots));
+        if (result === true) {
+            AndroidBridge.showToast("时间段导入成功!");
+        } else {
+            AndroidBridge.showToast("时间段导入失败,请查看日志!");
+        }
+    } catch (err) {
+        console.error("时间段导入失败:", err);
+        AndroidBridge.showToast("时间段导入失败:" + err.message);
+    }
+}
+
+
+// ====================== 主流程 ======================
+async function runImportFlow() {
+    AndroidBridge.showToast("课程导入流程即将开始...");
+
+    // 1️⃣ 获取学年学期
+    const yearTermData = await fetchSchoolYearTerms();
+    if (!yearTermData) {
+        AndroidBridge.notifyTaskCompletion();
+        return;
+    }
+
+    // 2️⃣ 用户选择
+    const selection = await selectYearAndTerm(yearTermData.schoolYears, yearTermData.schoolTerms);
+    if (!selection) {
+        AndroidBridge.showToast("用户取消选择!");
+        AndroidBridge.notifyTaskCompletion();
+        return;
+    }
+
+    // 3️⃣ 异步获取课程并处理
+    const courses = await fetchCoursesForAllWeeks(selection.year, selection.term);
+    if (!courses) {
+        AndroidBridge.notifyTaskCompletion();
+        return;
+    }
+
+    // 4️⃣ 保存课程
+    const saveResult = await saveCourses(courses);
+    if (!saveResult) {
+        AndroidBridge.notifyTaskCompletion();
+        return;
+    }
+
+    // 5️⃣ 导入预设时间段
+    await importPresetTimeSlots();
+
+    AndroidBridge.showToast("所有任务完成!");
+    AndroidBridge.notifyTaskCompletion();
+}
+
+// 启动流程
+runImportFlow();