Преглед на файлове

add:添加山东药品食品职业学院教务

XingHeYuZhuan преди 3 седмици
родител
ревизия
6cc6e5a9fc
променени са 3 файла, в които са добавени 180 реда и са изтрити 1 реда
  1. 6 1
      index/root_index.yaml
  2. 9 0
      resources/SDDFVC/adapters.yaml
  3. 165 0
      resources/SDDFVC/sddfvc.js

+ 6 - 1
index/root_index.yaml

@@ -111,4 +111,9 @@ schools:
   - id: "FJCPC"
     name: "福建船政交通职业学院"
     initial: "F"
-    resource_folder: "FJCPC"        
+    resource_folder: "FJCPC"
+
+  - id: "SDDFVC"
+    name: "山东药品食品职业学院"
+    initial: "S"
+    resource_folder: "SDDFVC"       

+ 9 - 0
resources/SDDFVC/adapters.yaml

@@ -0,0 +1,9 @@
+# resources/SDDFVC/adapters.yaml
+adapters:
+  - adapter_id: "SDDFVC"
+    adapter_name: "山东药品食品职业学院教务"
+    category: "BACHELOR_AND_ASSOCIATE"
+    asset_js_path: "sddfvc.js"
+    import_url: "http://jwxt.sddfvc.edu.cn/mobile/login"
+    maintainer: "星河欲转"
+    description: "山东药品食品职业学院教务适配,非本校开发者适配如果有误建议提交issues"

+ 165 - 0
resources/SDDFVC/sddfvc.js

@@ -0,0 +1,165 @@
+// 山东药品食品职业学院(sddfvc.edu.cn) 拾光课程表适配脚本
+// 非该大学开发者适配,开发者无法及时发现问题
+// 出现问题请提联系开发者或者提交pr更改,这更加快速
+
+// 数据解析函数
+
+/**
+ * 将周次字符串结合单双周标识解析为数字数组
+ * @param {string} zcString "7-15,17-20"
+ * @param {number} dsz 0: 全周, 1: 单周, 2: 双周, -1: 全周
+ */
+function parseWeeks(zcString, dsz) {
+    let weeks = [];
+    if (!zcString) return weeks;
+
+    // 解析基础周次
+    zcString.split(',').forEach(part => {
+        if (part.includes('-')) {
+            const [start, end] = part.split('-').map(Number);
+            for (let i = start; i <= end; i++) weeks.push(i);
+        } else {
+            weeks.push(Number(part));
+        }
+    });
+
+    // 处理单双周过滤
+    if (dsz === 1) {
+        weeks = weeks.filter(w => w % 2 !== 0);
+    } else if (dsz === 2) {
+        weeks = weeks.filter(w => w % 2 === 0);
+    }
+    return weeks;
+}
+
+/**
+ * 转换课程格式为应用模型
+ */
+function parseCoursesToModel(sourceData) {
+    const resultCourses = [];
+    const days = ["xq1", "xq2", "xq3", "xq4", "xq5", "xq6", "xq7"];
+    const sectionMap = { "1": 1, "3": 2, "5": 3, "7": 4 };
+
+    days.forEach((dayKey, index) => {
+        const dayContent = sourceData[dayKey];
+        if (!dayContent) return;
+
+        Object.keys(dayContent).forEach(slotNum => {
+            const mappedSection = sectionMap[slotNum];
+            if (!mappedSection) return;
+
+            Object.values(dayContent[slotNum]).forEach(item => {
+                const courseName = item.skbj[0][1];
+
+                Object.values(item.pkmx).forEach(detail => {
+                    if (!detail) return;
+
+                    const computedWeeks = parseWeeks(detail.zc.zc, detail.zc.dsz);
+                    if (computedWeeks.length === 0) return;
+
+                    resultCourses.push({
+                        "name": courseName,
+                        "teacher": detail.teacher[0]?.xm || "未知教师",
+                        "position": detail.classroom || "未知地点",
+                        "day": index + 1,
+                        "startSection": mappedSection,
+                        "endSection": mappedSection,
+                        "weeks": computedWeeks
+                    });
+                });
+            });
+        });
+    });
+    return resultCourses;
+}
+
+// 网络与交互业务函数
+
+/**
+ * 保存课表全局配置
+ */
+async function saveAppConfig() {
+    const config = {
+        "defaultClassDuration": 90,
+        "defaultBreakDuration": 15,
+        "firstDayOfWeek": 1
+    };
+    return await window.AndroidBridgePromise.saveCourseConfig(JSON.stringify(config));
+}
+
+/**
+ * 保存时间段配置
+ */
+async function saveAppTimeSlots() {
+    const timeSlots = [
+        { "number": 1, "startTime": "08:30", "endTime": "10:00" },
+        { "number": 2, "startTime": "10:15", "endTime": "11:45" },
+        { "number": 3, "startTime": "13:30", "endTime": "15:00" },
+        { "number": 4, "startTime": "15:15", "endTime": "16:45" }
+    ];
+    return await window.AndroidBridgePromise.savePresetTimeSlots(JSON.stringify(timeSlots));
+}
+
+/**
+ * 获取并让用户选择学期 ID
+ */
+async function getSelectedSemesterId(apiToken) {
+    const xqRes = await fetch(`http://jwxt.sddfvc.edu.cn/mobile/student/mobile_kcb_xq?api_token=${apiToken}`);
+    const xqJson = await xqRes.json();
+    const xqList = xqJson.data.xq_all;
+    const currentXq = xqJson.data.xq_current;
+
+    const xqNames = xqList.map(item => item.xqmc);
+    const defaultIdx = xqList.findIndex(item => item.id === currentXq.id);
+
+    const selectedIdx = await window.AndroidBridgePromise.showSingleSelection(
+        "请确认导入学期",
+        JSON.stringify(xqNames),
+        defaultIdx !== -1 ? defaultIdx : xqNames.length - 1
+    );
+
+    return selectedIdx !== null ? xqList[selectedIdx].id : null;
+}
+
+// 流程控制
+
+async function runImportFlow() {
+    try {
+        const tokenMatch = document.cookie.match(/api_token=([^;]+)/);
+        if (!tokenMatch) {
+            AndroidBridge.showToast("未检测到登录状态,请先登录");
+            return;
+        }
+        const apiToken = tokenMatch[1];
+
+        const semesterId = await getSelectedSemesterId(apiToken);
+        if (!semesterId) {
+            AndroidBridge.showToast("导入已取消");
+            return;
+        }
+
+        AndroidBridge.showToast("正在获取课表数据...");
+        const kcbRes = await fetch(`http://jwxt.sddfvc.edu.cn/mobile/student/mobile_kcb?api_token=${apiToken}&xq=${semesterId}`);
+        const kcbJson = await kcbRes.json();
+
+        const finalCourses = parseCoursesToModel(kcbJson.data);
+        if (finalCourses.length === 0) {
+            AndroidBridge.showToast("该学期暂无课程");
+            return;
+        }
+
+        AndroidBridge.showToast("正在保存配置...");
+        await saveAppConfig();
+        await saveAppTimeSlots();
+        await window.AndroidBridgePromise.saveImportedCourses(JSON.stringify(finalCourses));
+        
+        AndroidBridge.showToast(`成功导入 ${finalCourses.length} 条课程明细`);
+        AndroidBridge.notifyTaskCompletion();
+
+    } catch (error) {
+        console.error(error);
+        AndroidBridge.showToast("异常: " + error.message);
+    }
+}
+
+runImportFlow();