fjcpc.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // 福建船政交通职业学院(fjcpc.edu.cn)拾光课程表适配脚本
  2. // 非该大学开发者适配,开发者无法及时发现问题
  3. // 出现问题请提联系开发者或者提交pr更改,这更加快速
  4. // 引导
  5. async function promptUserToStart() {
  6. return await window.AndroidBridgePromise.showAlert(
  7. "公告",
  8. "即将开始导入请确保已经登录并跳转到已显示课表位置",
  9. "好的,开始"
  10. );
  11. }
  12. /**
  13. * 选择作息时间(双季适配)
  14. */
  15. async function selectTimeSchedule() {
  16. const semesters = ["夏季作息", "冬季作息"];
  17. const selectedIndex = await window.AndroidBridgePromise.showSingleSelection(
  18. "选择作息时间",
  19. JSON.stringify(semesters),
  20. -1
  21. );
  22. if (selectedIndex === null) return null;
  23. // 预设节次数据
  24. const summerTime = [
  25. { number: 1, startTime: "08:00", endTime: "08:45" },
  26. { number: 2, startTime: "08:55", endTime: "09:40" },
  27. { number: 3, startTime: "10:00", endTime: "10:45" },
  28. { number: 4, startTime: "10:55", endTime: "11:40" },
  29. { number: 5, startTime: "14:30", endTime: "15:15" },
  30. { number: 6, startTime: "15:25", endTime: "16:10" },
  31. { number: 7, startTime: "16:30", endTime: "17:15" },
  32. { number: 8, startTime: "17:25", endTime: "18:10" },
  33. { number: 9, startTime: "19:20", endTime: "20:05" },
  34. { number: 10, startTime: "20:15", endTime: "21:00" }
  35. ];
  36. const winterTime = [
  37. { number: 1, startTime: "08:00", endTime: "08:45" },
  38. { number: 2, startTime: "08:55", endTime: "09:40" },
  39. { number: 3, startTime: "10:00", endTime: "10:45" },
  40. { number: 4, startTime: "10:55", endTime: "11:40" },
  41. { number: 5, startTime: "14:00", endTime: "14:45" },
  42. { number: 6, startTime: "14:55", endTime: "15:40" },
  43. { number: 7, startTime: "16:00", endTime: "16:45" },
  44. { number: 8, startTime: "16:55", endTime: "17:40" },
  45. { number: 9, startTime: "19:00", endTime: "19:45" },
  46. { number: 10, startTime: "19:55", endTime: "20:40" }
  47. ];
  48. return selectedIndex === 0 ? summerTime : winterTime;
  49. }
  50. /**
  51. * 获取并解析网络数据
  52. */
  53. async function fetchAndParseData() {
  54. // 自动提取凭证
  55. const match = document.cookie.match(/Admin-Token=([^;]+)/);
  56. if (!match) {
  57. AndroidBridge.showToast("未发现登录凭证,请登录后重试");
  58. return null;
  59. }
  60. const token = decodeURIComponent(match[1]);
  61. try {
  62. const response = await fetch("https://211-80-233-108.webvpn.fjcpc.edu.cn/jwxt/manager/bjxx/kb/selectStudentLeader", {
  63. "headers": { "authorization": token },
  64. "method": "GET"
  65. });
  66. const json = await response.json();
  67. const { xlxx, xskbList } = json.data;
  68. // 计算日期
  69. const date = new Date(xlxx.rq);
  70. const day = date.getDay();
  71. const diffToMonday = (day === 0 ? 6 : day - 1);
  72. const firstMonday = new Date(date);
  73. firstMonday.setDate(date.getDate() - diffToMonday - (parseInt(xlxx.zc) - 1) * 7);
  74. // 解析课程列表
  75. const days = { "Mon": 1, "Tues": 2, "Wed": 3, "Thu": 4, "Fri": 5, "Sat": 6, "Sun": 7 };
  76. const slots = ["1_2", "3_4", "5_6", "7_8", "9_10", "11_12"];
  77. const courses = [];
  78. for (const [dk, dv] of Object.entries(days)) {
  79. slots.forEach(sk => {
  80. const raw = xskbList[`${dk}${sk}`];
  81. if (raw && raw.includes('◇')) {
  82. raw.split('\n').filter(l => l.includes('◇')).forEach(line => {
  83. const p = line.split('◇');
  84. const timePart = p[1];
  85. const secStr = timePart.split('(')[1].replace(')', '');
  86. const sec = secStr.split(',');
  87. courses.push({
  88. name: p[0].split('<')[1].trim(),
  89. teacher: p[4].trim(),
  90. position: p[2].trim(),
  91. day: dv,
  92. startSection: parseInt(sec[0]),
  93. endSection: parseInt(sec[1]),
  94. weeks: ((s) => {
  95. const ws = [];
  96. s.split(',').forEach(v => {
  97. if (v.includes('-')) {
  98. const [b, e] = v.split('-').map(Number);
  99. for (let i = b; i <= e; i++) ws.push(i);
  100. } else ws.push(Number(v));
  101. });
  102. return ws;
  103. })(timePart.split('(')[0])
  104. });
  105. });
  106. }
  107. });
  108. }
  109. return {
  110. config: {
  111. semesterStartDate: firstMonday.toISOString().split('T')[0],
  112. semesterTotalWeeks: 24,
  113. firstDayOfWeek: 1
  114. },
  115. courses: courses
  116. };
  117. } catch (e) {
  118. AndroidBridge.showToast("数据解析失败: " + e.message);
  119. return null;
  120. }
  121. }
  122. // 编排主流程
  123. async function runImportFlow() {
  124. AndroidBridge.showToast("课程导入流程开始...");
  125. // 公告和前置检查
  126. const alertConfirmed = await promptUserToStart();
  127. if (!alertConfirmed) {
  128. AndroidBridge.showToast("用户取消了导入。");
  129. return;
  130. }
  131. // 选择作息时间
  132. const timeSlots = await selectTimeSchedule();
  133. if (timeSlots === null) {
  134. AndroidBridge.showToast("已取消选择作息。");
  135. return;
  136. }
  137. // 网络请求和数据解析
  138. const data = await fetchAndParseData();
  139. if (data === null) {
  140. return;
  141. }
  142. // 保存课表配置
  143. try {
  144. await window.AndroidBridgePromise.saveCourseConfig(JSON.stringify(data.config));
  145. } catch (e) {
  146. AndroidBridge.showToast("保存配置失败");
  147. return;
  148. }
  149. // 课程数据保存
  150. try {
  151. await window.AndroidBridgePromise.saveImportedCourses(JSON.stringify(data.courses));
  152. AndroidBridge.showToast(`成功抓取 ${data.courses.length} 门课程!`);
  153. } catch (e) {
  154. AndroidBridge.showToast("保存课程数据失败");
  155. return;
  156. }
  157. // 导入时间段
  158. try {
  159. await window.AndroidBridgePromise.savePresetTimeSlots(JSON.stringify(timeSlots));
  160. AndroidBridge.showToast("作息时间同步成功");
  161. } catch (e) {
  162. console.error("作息保存失败:", e);
  163. }
  164. AndroidBridge.showToast("所有任务已完成!");
  165. AndroidBridge.notifyTaskCompletion();
  166. }
  167. runImportFlow();