NEAU_01.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /**
  2. * 解析 URP 系统的周次字符串
  3. * 支持处理:"1-16周", "1,3,5周", "1-16周(双)" 等各种奇葩格式
  4. */
  5. function parseWeeks(weekStr) {
  6. if (!weekStr) return [];
  7. let weeks = [];
  8. // 提取单双周标志,并剔除汉字
  9. let isOdd = weekStr.includes('单');
  10. let isEven = weekStr.includes('双');
  11. let cleanStr = weekStr.replace(/周|\(单\)|\(双\)|单|双/g, '').replace(/\s+/g, '');
  12. let parts = cleanStr.split(',');
  13. for (let part of parts) {
  14. if (part.includes('-')) {
  15. let [start, end] = part.split('-');
  16. let s = parseInt(start);
  17. let e = parseInt(end);
  18. for (let i = s; i <= e; i++) {
  19. if (isOdd && i % 2 === 0) continue;
  20. if (isEven && i % 2 !== 0) continue;
  21. if (!weeks.includes(i)) weeks.push(i);
  22. }
  23. } else {
  24. let w = parseInt(part);
  25. if (!isNaN(w) && !weeks.includes(w)) {
  26. if (isOdd && w % 2 === 0) continue;
  27. if (isEven && w % 2 !== 0) continue;
  28. weeks.push(w);
  29. }
  30. }
  31. }
  32. return weeks.sort((a, b) => a - b);
  33. }
  34. /**
  35. * 调用 URP 隐藏接口获取 JSON 课表
  36. */
  37. async function runImportFlow() {
  38. try {
  39. if (typeof window.AndroidBridge !== 'undefined') {
  40. AndroidBridge.showToast("正在通过数据接口获取课表...");
  41. } else {
  42. console.log("正在请求 URP 内部数据接口...");
  43. }
  44. // 1. 直接请求 URP 系统内部的课表 JSON 接口
  45. const apiUrl = '/student/courseSelect/thisSemesterCurriculum/ajaxStudentSchedule/callback';
  46. const response = await fetch(apiUrl, { method: 'GET' });
  47. if (!response.ok) {
  48. throw new Error(`接口请求失败,状态码: ${response.status}`);
  49. }
  50. const data = await response.json();
  51. // URP 的课程数据存放在 xkxx 这个数组的第0个对象里
  52. if (!data || !data.xkxx || !data.xkxx[0]) {
  53. const errMsg = "未获取到有效的课表数据,可能是当前学期暂无排课。";
  54. if (typeof window.AndroidBridgePromise !== 'undefined') {
  55. await window.AndroidBridgePromise.showAlert("提示", errMsg, "好的");
  56. } else {
  57. alert(errMsg);
  58. }
  59. return;
  60. }
  61. const coursesMap = data.xkxx[0];
  62. let parsedCourses = [];
  63. // ==========================================
  64. // 自动管理:直接从 URP 返回的 jcsjbs 字段提取并格式化作息时间
  65. // ==========================================
  66. let timeSlots = [];
  67. if (data.jcsjbs && Array.isArray(data.jcsjbs)) {
  68. timeSlots = data.jcsjbs.map(t => {
  69. // 辅助函数:将 "0810" 格式化为 "08:10"
  70. const formatTime = (timeStr) => {
  71. if (timeStr && timeStr.length === 4) {
  72. return timeStr.substring(0, 2) + ":" + timeStr.substring(2, 4);
  73. }
  74. return timeStr || "";
  75. };
  76. return {
  77. number: parseInt(t.jc),
  78. startTime: formatTime(t.kssj),
  79. endTime: formatTime(t.jssj)
  80. };
  81. });
  82. }
  83. // 2. 遍历 JSON 数据进行格式转换
  84. for (let key in coursesMap) {
  85. const courseInfo = coursesMap[key];
  86. // 跳过没有时间地点的课程(无课表课程)
  87. if (!courseInfo.timeAndPlaceList || courseInfo.timeAndPlaceList.length === 0) {
  88. continue;
  89. }
  90. // 一门课可能在一周内上多次,所以遍历 timeAndPlaceList
  91. courseInfo.timeAndPlaceList.forEach(tp => {
  92. let courseObj = {
  93. name: courseInfo.courseName || "未知课程",
  94. teacher: courseInfo.attendClassTeacher || "未知",
  95. isCustomTime: false
  96. };
  97. // 拼装地点:校区 + 教学楼 + 教室
  98. let campus = tp.campusName || "";
  99. let building = tp.teachingBuildingName || "";
  100. let room = tp.classroomName || "";
  101. let fullPosition = campus + building + room;
  102. courseObj.position = fullPosition ? fullPosition : "待定";
  103. // 解析时间
  104. courseObj.day = parseInt(tp.classDay);
  105. courseObj.startSection = parseInt(tp.classSessions);
  106. // 结束节次 = 开始节次 + 持续节次 - 1
  107. courseObj.endSection = courseObj.startSection + parseInt(tp.continuingSession) - 1;
  108. // 解析周次 (例如 "1-17周")
  109. courseObj.weeks = parseWeeks(tp.weekDescription);
  110. // 只有数据完整才加入
  111. if (courseObj.day && courseObj.startSection && courseObj.weeks.length > 0) {
  112. parsedCourses.push(courseObj);
  113. }
  114. });
  115. }
  116. if (parsedCourses.length === 0) {
  117. throw new Error("解析完成,但没有提取到包含时间的有效课程。");
  118. }
  119. const config = {
  120. "defaultClassDuration": 45,
  121. "defaultBreakDuration": 10
  122. };
  123. // 3. 浏览器测试环境,直接打印输出
  124. if (typeof window.AndroidBridgePromise === 'undefined') {
  125. console.log("【URP系统测试成功】提取的课程数据:\n", JSON.stringify(parsedCourses, null, 2));
  126. if (timeSlots.length > 0) {
  127. console.log("【URP系统测试成功】提取到的作息时间:\n", JSON.stringify(timeSlots, null, 2));
  128. } else {
  129. console.log("【URP系统测试成功】未获取到作息时间,将交由APP自动管理。");
  130. }
  131. alert(`解析成功!直接从接口抓取到 ${parsedCourses.length} 门课程。请打开F12控制台查看。`);
  132. return;
  133. }
  134. // 4. APP 环境保存数据
  135. await window.AndroidBridgePromise.saveCourseConfig(JSON.stringify(config));
  136. // 将格式化后的标准作息时间交给 APP 进行保存
  137. if (timeSlots.length > 0) {
  138. await window.AndroidBridgePromise.savePresetTimeSlots(JSON.stringify(timeSlots));
  139. }
  140. const saveResult = await window.AndroidBridgePromise.saveImportedCourses(JSON.stringify(parsedCourses));
  141. if (!saveResult) {
  142. AndroidBridge.showToast("保存课程失败,请重试!");
  143. return;
  144. }
  145. AndroidBridge.showToast(`成功导入 ${parsedCourses.length} 节课程!`);
  146. AndroidBridge.notifyTaskCompletion();
  147. } catch (error) {
  148. if (typeof window.AndroidBridge !== 'undefined') {
  149. AndroidBridge.showToast("导入发生异常: " + error.message);
  150. } else {
  151. console.error("【导入发生异常】", error);
  152. alert("导入发生异常: " + error.message);
  153. }
  154. }
  155. }
  156. // 启动导入流程
  157. runImportFlow();