فهرست منبع

适配河南师范大学

YIKE 1 ماه پیش
والد
کامیت
36a193d101
2فایلهای تغییر یافته به همراه300 افزوده شده و 1 حذف شده
  1. 8 1
      resources/HNSF/adapters.yaml
  2. 292 0
      resources/HNSF/hnsf_02.js

+ 8 - 1
resources/HNSF/adapters.yaml

@@ -6,4 +6,11 @@ adapters:
     asset_js_path: "hnsf_01.js"
     import_url: "https://jwc.htu.edu.cn/"
     maintainer: "星河欲转"
-    description: "河南师范大学适配教务,添加双季作息,非本校开发者适配如果有误建议提交issue"
+    description: "河南师范大学适配教务,添加双季作息,非本校开发者适配如果有误建议提交issue"
+  - adapter_id: "HNSF_02"
+    adapter_name: "河南师范大学适配教务"
+    category: "BACHELOR_AND_ASSOCIATE"
+    asset_js_path: "hnsf_02.js"
+    import_url: "https://jwc.htu.edu.cn/"
+    maintainer: "一颗"
+    description: "该作者没有添加说明"

+ 292 - 0
resources/HNSF/hnsf_02.js

@@ -0,0 +1,292 @@
+// ====================== 工具函数 ======================
+
+// 展开 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 selectMonth() {
+    try {
+        // 生成月份选项
+        const months = [];
+        const currentYear = new Date().getFullYear();
+        
+        // 生成当前学年(9月到次年6月)的月份选项
+        for (let month = 9; month <= 12; month++) {
+            months.push(`${currentYear}年${month}月`);
+        }
+        for (let month = 1; month <= 6; month++) {
+            months.push(`${currentYear + 1}年${month}月`);
+        }
+        
+        const selectedIndex = await window.AndroidBridgePromise.showSingleSelection(
+            "请选择要获取课程的月份",
+            JSON.stringify(months),
+            0
+        );
+        
+        if (selectedIndex === null) return null;
+        
+        const selectedMonth = months[selectedIndex];
+        const year = parseInt(selectedMonth.split('年')[0]);
+        const month = parseInt(selectedMonth.split('年')[1].split('月')[0]);
+        
+        // 计算该月的开始和结束日期
+        const startDate = new Date(year, month - 1, 1);
+        const endDate = new Date(year, month, 0); // 该月最后一天
+        
+        return {
+            startDate: startDate,
+            endDate: endDate,
+            year: year,
+            month: month
+        };
+    } catch (err) {
+        console.error("选择月份失败:", err);
+        return null;
+    }
+}
+
+// ====================== 异步获取课程数据 ======================
+async function fetchCoursesData() {
+    try {
+        // 让用户选择月份
+        const monthSelection = await selectMonth();
+        if (!monthSelection) {
+            AndroidBridge.showToast("用户取消选择月份!");
+            return null;
+        }
+        
+        // 格式化日期为API需要的格式
+        const formatDate = (date) => {
+            const year = date.getFullYear();
+            const month = String(date.getMonth() + 1).padStart(2, '0');
+            const day = String(date.getDate()).padStart(2, '0');
+            return `${year}-${month}-${day}+00%3A00%3A00`;
+        };
+        
+        const d1 = formatDate(monthSelection.startDate);
+        const d2 = formatDate(monthSelection.endDate);
+        
+        
+        const res = await fetch("https://jwc.htu.edu.cn/new/desktop/getCalendar", {
+            method: 'POST',
+            headers: {
+                'Content-Type': 'application/x-www-form-urlencoded',
+            },
+            body: `d1=${d1}&d2=${d2}`
+        });
+        const json = await res.json();
+        
+        
+        return json; // 直接返回课程数据数组
+    } catch (err) {
+        console.error("获取课程数据失败:", err);
+        AndroidBridge.showToast("获取课程数据失败:" + err.message);
+        return null;
+    }
+}
+
+// ====================== 处理新格式的课程数据 ======================
+async function processCoursesData(coursesData) {
+    if (!coursesData || !Array.isArray(coursesData)) {
+        return null;
+    }
+
+    const allCourses = [];
+
+    coursesData.forEach((course) => {
+        // 解析节次代码 (如 "0910" -> 第9节到第10节)
+        const jcdm = course.jcdm || "";
+        if (!jcdm || jcdm.length < 4) {
+            return;
+        }
+
+        const startSection = parseInt(jcdm.substring(0, 2));
+        const endSection = parseInt(jcdm.substring(2, 4));
+        
+        // 解析周次 (如 "10" -> [10])
+        const weeks = parseWeeks(course.zc || "");
+        if (!weeks.length) {
+            return;
+        }
+
+        // 解析星期 (如 "3" -> 星期三)
+        const day = parseInt(course.xq || "1");
+        if (day < 1 || day > 7) {
+            return;
+        }
+
+        // 处理地点格式,按照 [校本部]西校区新联楼0303 的格式
+        let position = course.jxcdmc || "";
+        const xqmc = course.xqmc || "校本部";
+        if (position && !position.startsWith("[")) {
+            position = `[${xqmc}]${position}`;
+        }
+
+        const processedCourse = {
+            name: course.kcmc || "",
+            teacher: course.teaxms || "",
+            position: position,
+            day: day,
+            startSection: startSection,
+            endSection: endSection,
+            weeks: weeks
+        };
+        
+        allCourses.push(processedCourse);
+    });
+
+    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;
+    }
+}
+
+// ====================== 导入预设时间段(一天5节大课,10节小课) ======================
+async function importPresetTimeSlots() {
+    // 一天5节大课,10节小课的时间安排
+    const presetTimeSlots = [
+        { number: 1, startTime: "08:00", endTime: "08:45" }, // 第1节
+        { number: 2, startTime: "08:45", endTime: "09:30" }, // 第2节
+        { number: 3, startTime: "09:50", endTime: "10:35" }, // 第3节
+        { number: 4, startTime: "10:35", endTime: "11:20" }, // 第4节
+        { number: 5, startTime: "14:00", endTime: "14:45" }, // 第5节
+        { number: 6, startTime: "14:45", endTime: "15:30" }, // 第6节
+        { number: 7, startTime: "15:50", endTime: "16:35" }, // 第7节
+        { number: 8, startTime: "16:35", endTime: "17:20" }, // 第8节
+        { number: 9, startTime: "19:00", endTime: "19:45" }, // 第9节
+        { number: 10, startTime: "19:45", endTime: "20:30" } // 第10节
+    ];
+    
+    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 showAnnouncement() {
+    try {
+        const announcement = `
+课程导入工具使用说明:
+
+1. 本工具用于从教务系统获取课程数据
+2. 请确保已登录教务系统
+3. 选择要获取课程的月份
+4. 工具会自动下载原始数据和处理后的数据
+5. 支持一天10节课的时间安排
+6. 自动合并重复课程
+
+使用前请确认网络连接正常!
+        `.trim();
+        
+        await window.AndroidBridgePromise.showAlert(
+            "课程导入工具公告",
+            announcement
+        );
+    } catch (err) {
+        console.error("显示公告失败:", err);
+        // 如果弹窗失败,使用Toast提示
+        AndroidBridge.showToast("课程导入工具启动中...");
+    }
+}
+
+// ====================== 主流程 ======================
+async function runImportFlow() {
+    // 显示公告
+    await showAnnouncement();
+    
+    AndroidBridge.showToast("课程导入流程即将开始...");
+
+    // 1️⃣ 获取课程数据
+    const coursesData = await fetchCoursesData();
+    if (!coursesData) {
+        AndroidBridge.notifyTaskCompletion();
+        return;
+    }
+
+    // 2️⃣ 处理课程数据
+    const courses = await processCoursesData(coursesData);
+    if (!courses) {
+        AndroidBridge.showToast("没有找到有效的课程数据!");
+        AndroidBridge.notifyTaskCompletion();
+        return;
+    }
+
+    // 3️⃣ 保存课程
+    const saveResult = await saveCourses(courses);
+    if (!saveResult) {
+        AndroidBridge.notifyTaskCompletion();
+        return;
+    }
+
+    // 4️⃣ 导入预设时间段
+    await importPresetTimeSlots();
+
+    AndroidBridge.showToast("所有任务完成!");
+    AndroidBridge.notifyTaskCompletion();
+}
+
+// 启动流程
+runImportFlow();