Просмотр исходного кода

Merge pull request #244 from sLingli/main

修复泰山学院教务脚本在无地点网课时的内容错位
星河欲转 2 недель назад
Родитель
Сommit
48dedced05
2 измененных файлов с 55 добавлено и 22 удалено
  1. 1 1
      resources/TSU/adapters.yaml
  2. 54 21
      resources/TSU/tsu_01.js

+ 1 - 1
resources/TSU/adapters.yaml

@@ -6,4 +6,4 @@ adapters:
     asset_js_path: "tsu_01.js"
     import_url: "http://jwxt.tsu.edu.cn"
     maintainer: "素绫理"
-    description: "泰山学院青果教务系统课表适配"
+    description: "泰山学院青果教务系统课表适配,登陆后点击左侧【教学安排】,再点击【执行导入】即可,导入后不要忘记设置本学期的开学日期"

+ 54 - 21
resources/TSU/tsu_01.js

@@ -16,11 +16,10 @@ function findTable(win) {
     const t = Array.from(win.document.querySelectorAll('table'))
         .find(x => x.innerText.includes("星期一") && x.innerText.includes("["));
     if (t) return t;
-    
     for (let i = 0; i < win.frames.length; i++) {
-        try { 
-            const st = findTable(win.frames[i]); 
-            if (st) return st; 
+        try {
+            const st = findTable(win.frames[i]);
+            if (st) return st;
         } catch (e) {}
     }
     return null;
@@ -28,7 +27,6 @@ function findTable(win) {
 
 async function fetchAndParseCourses() {
     const table = findTable(window);
-    
     if (!table) {
         throw new Error("未检测到课表数据,请确保已切换到显示课表的页面!");
     }
@@ -37,7 +35,7 @@ async function fetchAndParseCourses() {
     Array.from(table.rows).forEach(row => {
         const cells = Array.from(row.cells);
         if (cells.length < 7) return;
-        
+
         cells.forEach((cell, colIndex) => {
             const distanceToLast = cells.length - 1 - colIndex;
             if (distanceToLast > 6) return;
@@ -45,21 +43,61 @@ async function fetchAndParseCourses() {
             const rawText = cell.innerText.trim();
             if (!rawText.includes('[')) return;
 
-            const lines = rawText.split('\n').map(l => l.trim()).filter(l => l);
-            lines.forEach((line, i) => {
-                const match = line.match(/([\d\-,]+)\[(\d+)-(\d+)\]/);
+            // 过滤空行、清理隐藏的乱码字符
+            const lines = rawText.split('\n').map(l => l.replace(/[\s\u200B-\u200D\uFEFF]/g, '').trim()).filter(l => l);
+
+            // 找出所有时间的行号(锚点)
+            const timeIndices = [];
+            lines.forEach((line, index) => {
+                if (/([\d\-,]+)\[(\d+)-(\d+)\]/.test(line)) {
+                    timeIndices.push(index);
+                }
+            });
+
+            // 遍历每个锚点,精准抓取
+            timeIndices.forEach((currTimeIdx, k) => {
+                const nextTimeIdx = (k + 1 < timeIndices.length) ? timeIndices[k + 1] : lines.length;
+                const match = lines[currTimeIdx].match(/([\d\-,]+)\[(\d+)-(\d+)\]/);
+                
                 if (match) {
+                    // 1. 抓取课名和老师
                     let name = "未知课程";
-                    if (i >= 2) name = lines[i-2];
-                    else if (i >= 1) name = lines[i-1];
+                    let teacher = "未知教师";
+                    let nameTeacherLines = (k === 0) ? lines.slice(0, currTimeIdx) : lines.slice(timeIndices[k - 1] + 1, currTimeIdx);
+                    
+                    if (nameTeacherLines.length > 2) {
+                        nameTeacherLines = nameTeacherLines.slice(nameTeacherLines.length - 2);
+                    }
+
+                    if (nameTeacherLines.length >= 2) {
+                        name = nameTeacherLines[0];
+                        teacher = nameTeacherLines[1];
+                    } else if (nameTeacherLines.length === 1) {
+                        name = nameTeacherLines[0];
+                        teacher = ""; // 没写老师
+                    }
+
+                    // 2. 抓取地点
+                    let position = "";
+                    const gap = nextTimeIdx - currTimeIdx - 1; // 距离下个时间(或结尾)差几行
                     
-                    let teacher = (i >= 1 && !lines[i-1].includes('[')) ? lines[i-1] : "未知教师";
-                    let position = (i < lines.length - 1) ? lines[i+1] : "未知地点";
+                    if (k === timeIndices.length - 1) {
+                        // 最后一门课,后面全是地点
+                        if (gap > 0) position = lines.slice(currTimeIdx + 1).join(' ');
+                    } else {
+                        if (gap === 3) {
+                            position = lines[currTimeIdx + 1]; // 刚好3行,第1行必是地点
+                        } else if (gap > 3) {
+                            position = lines.slice(currTimeIdx + 1, nextTimeIdx - 2).join(' '); // 地点占了多行
+                        } else {
+                            position = ""; // <= 2行说明全被下节课的名字占了,这节课没地点(网课)
+                        }
+                    }
 
                     rawItems.push({
-                        name: name.replace(/\s/g, ""),
-                        teacher: teacher.replace(/\s/g, ""),
-                        position: position.replace(/\s/g, ""),
+                        name: name,
+                        teacher: teacher,
+                        position: position,
                         day: day,
                         startSection: parseInt(match[2]),
                         endSection: parseInt(match[3]),
@@ -87,12 +125,10 @@ async function fetchAndParseCourses() {
     groupMap.forEach((weekMap, key) => {
         const [name, teacher, position, day] = key.split('|');
         const patternMap = new Map();
-        
         Object.keys(weekMap).forEach(w => {
             const week = parseInt(w);
             const sections = Array.from(weekMap[week]).sort((a, b) => a - b);
             if (sections.length === 0) return;
-            
             let start = sections[0];
             for (let i = 0; i < sections.length; i++) {
                 if (i === sections.length - 1 || sections[i+1] !== sections[i] + 1) {
@@ -103,7 +139,6 @@ async function fetchAndParseCourses() {
                 }
             }
         });
-        
         patternMap.forEach((weeks, pKey) => {
             const [sStart, sEnd] = pKey.split('-').map(Number);
             finalCourses.push({
@@ -122,13 +157,11 @@ async function runImportFlow() {
     try {
         AndroidBridge.showToast("泰山学院引擎启动,抓取数据中...");
         const courses = await fetchAndParseCourses();
-        
         if (!courses || courses.length === 0) {
             AndroidBridge.showToast("解析完成,但当前课表为空");
             AndroidBridge.notifyTaskCompletion();
             return;
         }
-        
         const saveResult = await window.AndroidBridgePromise.saveImportedCourses(JSON.stringify(courses));
         if (saveResult === true) {
             AndroidBridge.showToast(`导入大成功!合并生成 ${courses.length} 个课块`);