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

add: 添加星链课表分享码导入功能

XingHeYuZhuan преди 7 часа
родител
ревизия
7c5acb2e4b
променени са 2 файла, в които са добавени 142 реда и са изтрити 0 реда
  1. 8 0
      resources/GLOBAL_TOOLS/adapters.yaml
  2. 134 0
      resources/GLOBAL_TOOLS/starlink.js

+ 8 - 0
resources/GLOBAL_TOOLS/adapters.yaml

@@ -23,3 +23,11 @@ adapters:
     import_url: "https://i.wakeup.fun/"
     maintainer: "星河欲转"
     description: "首先,先去wakeup获取分享口令,然后点击本适配,进入后不需要管网页,点击\"执行导入\"输入你刚刚获取的分享口令就好\n 特别鸣谢 钴-60 提供的思路"      
+
+  - adapter_id: "StarLink"
+    adapter_name: "星链课表分享码导入"
+    category: "GENERAL_TOOL"
+    asset_js_path: "starlink.js"
+    import_url: "https://api.starlinkkb.cn/"
+    maintainer: "星河欲转"
+    description: "首先,先去星链课表获取分享码,然后点击本适配,进入后不需要管网页,点击\"执行导入\"输入你刚刚获取的分享码就好"        

+ 134 - 0
resources/GLOBAL_TOOLS/starlink.js

@@ -0,0 +1,134 @@
+/**
+ * 星链课表分享导入脚本
+ */
+
+// 输入验证
+function validateInput(input) {
+    if (!input || input.trim().length === 0) return "请输入分享码!";
+    return false;
+}
+
+// 提取分享码
+function extractShareCode(text) {
+    const structuredRegex = /输入:\s*([^(\s]+)/;
+    const fallbackRegex = /([a-zA-Z0-9-]{5,20})/;
+
+    const matchA = text.match(structuredRegex);
+    if (matchA && matchA[1]) return matchA[1].trim();
+
+    const matchB = text.match(fallbackRegex);
+    if (matchB) return matchB[1].trim();
+
+    return text.trim();
+}
+
+// 课程去重与合并
+function processAndMergeCourses(courses) {
+    if (!courses || courses.length === 0) return [];
+
+    // 排序:星期 > 课程名 > 教师 > 教室 > 周次 > 起始节次
+    courses.sort((a, b) => 
+        a.day - b.day || 
+        (a.name || "").localeCompare(b.name || "") || 
+        (a.teacher || "").localeCompare(b.teacher || "") || 
+        (a.position || "").localeCompare(b.position || "") || 
+        JSON.stringify(a.weeks).localeCompare(JSON.stringify(b.weeks)) ||
+        a.startSection - b.startSection
+    );
+
+    const mergedResults = [];
+    courses.forEach(current => {
+        if (mergedResults.length === 0) {
+            mergedResults.push(current);
+            return;
+        }
+
+        const last = mergedResults[mergedResults.length - 1];
+
+        // 完全重复过滤
+        const isDuplicate = 
+            last.day === current.day &&
+            last.name === current.name &&
+            last.teacher === current.teacher &&
+            last.position === current.position &&
+            last.startSection === current.startSection &&
+            last.endSection === current.endSection &&
+            JSON.stringify(last.weeks) === JSON.stringify(current.weeks);
+
+        if (isDuplicate) return;
+
+        // 连堂课合并
+        const canMerge = 
+            last.day === current.day &&
+            last.name === current.name &&
+            last.teacher === current.teacher &&
+            last.position === current.position &&
+            JSON.stringify(last.weeks) === JSON.stringify(current.weeks) &&
+            current.startSection <= last.endSection + 1; 
+
+        if (canMerge) {
+            last.endSection = Math.max(last.endSection, current.endSection);
+        } else {
+            mergedResults.push(current);
+        }
+    });
+
+    return mergedResults;
+}
+
+// 主程序
+async function runStarlinkImport() {
+    try {
+        const userInput = await window.AndroidBridgePromise.showPrompt(
+            "导入星链课表",
+            "请粘贴分享文案(包含分享码)",
+            "",
+            "validateInput"
+        );
+
+        if (!userInput) return;
+
+        const shareCode = extractShareCode(userInput);
+        const apiUrl = `https://api.starlinkkb.cn/share/curriculum/${shareCode}`;
+        
+        AndroidBridge.showToast("正在同步云端数据...");
+
+        const response = await fetch(apiUrl);
+        if (!response.ok) throw new Error("分享码已失效或网络异常");
+
+        const resJson = await response.json();
+        const data = resJson.data;
+
+        // 数据映射
+        const rawCourses = data.courses.map(c => ({
+            name: c.name,
+            teacher: (c.teacher && c.teacher !== "无") ? c.teacher : "未知",
+            position: (c.location && c.location.replace(/^@/, '').trim() !== "") 
+                        ? c.location.replace(/^@/, '').trim() 
+                        : "未排地点",
+            day: c.weekday,
+            startSection: c.startSection,
+            endSection: c.endSection,
+            weeks: c.weeks
+        }));
+
+        const finalCourses = processAndMergeCourses(rawCourses);
+
+        const config = {
+            semesterStartDate: data.startDate ? data.startDate.substring(0, 10) : null,
+            semesterTotalWeeks: data.totalWeeks || 20
+        };
+
+        await window.AndroidBridgePromise.saveCourseConfig(JSON.stringify(config));
+        const success = await window.AndroidBridgePromise.saveImportedCourses(JSON.stringify(finalCourses));
+
+        if (success) {
+            AndroidBridge.showToast("导入成功!");
+            AndroidBridge.notifyTaskCompletion();
+        }
+    } catch (e) {
+        await window.AndroidBridgePromise.showAlert("导入失败", e.message, "确定");
+    }
+}
+
+runStarlinkImport();