jstc_01.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. // 江苏旅游职业学院(jstc.edu.cn) 拾光课程表适配脚本
  2. // 非该大学开发者适配,开发者无法及时发现问题
  3. // 出现问题请提issues或者提交pr更改,这更加快速
  4. // 不确定是否还有效的数据 仅保留代码内部不做调用
  5. const presetTimeSlots_oldFunction = [
  6. { number: 1, startTime: "08:00", endTime: "08:45" },
  7. { number: 2, startTime: "08:50", endTime: "09:35" },
  8. { number: 3, startTime: "09:55", endTime: "10:40" },
  9. { number: 4, startTime: "10:45", endTime: "11:30" },
  10. { number: 5, startTime: "11:35", endTime: "12:20" },
  11. { number: 6, startTime: "14:00", endTime: "14:45" },
  12. { number: 7, startTime: "14:50", endTime: "15:35" },
  13. { number: 8, startTime: "15:55", endTime: "16:40" },
  14. { number: 9, startTime: "16:45", endTime: "17:30" },
  15. { number: 10, startTime: "19:00", endTime: "19:45" },
  16. { number: 11, startTime: "19:50", endTime: "20:35" }
  17. ];
  18. const presetTimeSlots = [
  19. { number: 1, startTime: "08:00", endTime: "08:40" },
  20. { number: 2, startTime: "08:50", endTime: "09:30" },
  21. { number: 3, startTime: "09:50", endTime: "10:30" },
  22. { number: 4, startTime: "10:40", endTime: "11:20" },
  23. { number: 5, startTime: "11:30", endTime: "12:10" },
  24. { number: 6, startTime: "14:00", endTime: "14:40" },
  25. { number: 7, startTime: "14:50", endTime: "15:30" },
  26. { number: 8, startTime: "15:50", endTime: "16:30" },
  27. { number: 9, startTime: "16:40", endTime: "17:20" },
  28. { number: 10, startTime: "19:00", endTime: "19:40" },
  29. { number: 11, startTime: "19:50", endTime: "20:30" }
  30. ];
  31. /**
  32. * 获取学期下拉列表选项
  33. */
  34. async function fetchSemesters() {
  35. try {
  36. const res = await fetch("https://jwxt.jstc.edu.cn/student/for-std/course-table", {
  37. headers: {
  38. "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
  39. "x-requested-with": "XMLHttpRequest"
  40. },
  41. method: "GET",
  42. credentials: "include"
  43. });
  44. if (!res.ok) return null;
  45. const htmlText = await res.text();
  46. const parser = new DOMParser();
  47. const doc = parser.parseFromString(htmlText, "text/html");
  48. const select = doc.getElementById("allSemesters");
  49. if (!select) return null;
  50. const options = Array.from(select.querySelectorAll("option")).map(opt => ({
  51. label: opt.textContent.trim(),
  52. value: opt.value.trim()
  53. }));
  54. return options;
  55. } catch (e) {
  56. console.error("Fetch semesters failed:", e);
  57. return null;
  58. }
  59. }
  60. /**
  61. * 获取学期开学时间元数据
  62. */
  63. async function fetchSemesterMetadata(semesterId) {
  64. try {
  65. const res = await fetch(`https://jwxt.jstc.edu.cn/student/ws/semester/get/${semesterId}`, {
  66. headers: {
  67. "accept": "*/*",
  68. "x-requested-with": "XMLHttpRequest"
  69. },
  70. method: "GET",
  71. credentials: "include"
  72. });
  73. if (!res.ok) return null;
  74. const data = await res.json();
  75. return data.startDate || null;
  76. } catch (e) {
  77. console.error("Fetch semester metadata failed:", e);
  78. return null;
  79. }
  80. }
  81. /**
  82. * 获取并解析课表原数据
  83. */
  84. async function fetchAndParseCourses(semesterId) {
  85. try {
  86. const url = `https://jwxt.jstc.edu.cn/student/for-std/course-table/semester/${semesterId}/print-data?semesterId=${semesterId}&hasExperiment=true`;
  87. const res = await fetch(url, {
  88. headers: {
  89. "accept": "*/*",
  90. "x-requested-with": "XMLHttpRequest"
  91. },
  92. method: "GET",
  93. credentials: "include"
  94. });
  95. if (!res.ok) return null;
  96. const data = await res.json();
  97. if (!data || !Array.isArray(data.studentTableVms) || data.studentTableVms.length === 0) {
  98. return null;
  99. }
  100. const rawActivities = data.studentTableVms[0].activities || [];
  101. const parsedCourses = [];
  102. for (const act of rawActivities) {
  103. if (!act.courseName || !act.weekday || !act.startUnit || !act.endUnit || !Array.isArray(act.weekIndexes)) {
  104. continue;
  105. }
  106. const teacherName = Array.isArray(act.teachers) && act.teachers.length > 0
  107. ? act.teachers.map(t => t.replace(/\(\d+\)/g, '')).join(',')
  108. : '';
  109. parsedCourses.push({
  110. name: act.courseName.trim(),
  111. teacher: teacherName.trim(),
  112. position: (act.room || '').trim(),
  113. day: Number(act.weekday),
  114. startSection: Number(act.startUnit),
  115. endSection: Number(act.endUnit),
  116. weeks: act.weekIndexes.map(Number).sort((a, b) => a - b)
  117. });
  118. }
  119. return parsedCourses;
  120. } catch (e) {
  121. console.error("Fetch course data failed:", e);
  122. return null;
  123. }
  124. }
  125. /**
  126. * 流程控制
  127. */
  128. async function runImportFlow() {
  129. window.shiguangBridge.showToast("开始拉取学期列表...");
  130. // 获取学期列表
  131. const semesters = await fetchSemesters();
  132. if (!semesters || semesters.length === 0) {
  133. window.shiguangBridge.showToast("获取学期列表失败,请检查登录状态或网络");
  134. return;
  135. }
  136. const labels = semesters.map(s => s.label);
  137. const selectedIndex = await window.shiguangBridgePromise.showSingleSelection(
  138. "选择学期",
  139. JSON.stringify(labels),
  140. -1
  141. );
  142. if (selectedIndex === null || selectedIndex < 0) {
  143. window.shiguangBridge.showToast("操作已取消");
  144. return;
  145. }
  146. const selectedSemester = semesters[selectedIndex];
  147. // 并行获取元数据与课程表
  148. window.shiguangBridge.showToast("正在拉取课表数据...");
  149. const [startDate, courses] = await Promise.all([
  150. fetchSemesterMetadata(selectedSemester.value),
  151. fetchAndParseCourses(selectedSemester.value)
  152. ]);
  153. if (!courses || courses.length === 0) {
  154. window.shiguangBridge.showToast("未查询到有效课程数据");
  155. return;
  156. }
  157. // 保存学期配置
  158. const configData = {
  159. semesterStartDate: startDate,
  160. semesterTotalWeeks: 20
  161. };
  162. try {
  163. await window.shiguangBridgePromise.saveCourseConfig(JSON.stringify(configData));
  164. } catch (e) {
  165. window.shiguangBridge.showToast("配置保存异常: " + e.message);
  166. return;
  167. }
  168. // 保存课程列表
  169. try {
  170. await window.shiguangBridgePromise.saveImportedCourses(JSON.stringify(courses));
  171. } catch (e) {
  172. window.shiguangBridge.showToast("课程保存异常: " + e.message);
  173. return;
  174. }
  175. // 保存预设作息时间
  176. try {
  177. await window.shiguangBridgePromise.savePresetTimeSlots(JSON.stringify(presetTimeSlots));
  178. } catch (e) {
  179. window.shiguangBridge.showToast("作息时间保存异常: " + e.message);
  180. }
  181. window.shiguangBridge.showToast(`成功导入 ${courses.length} 门课程及作息时间!`);
  182. // 任务完成通知
  183. window.shiguangBridge.notifyTaskCompletion();
  184. }
  185. runImportFlow();