xjzfu.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. // 新疆政法学院教务系统课程表导入脚本
  2. // 适配: jwxt.xjzfu.edu.cn
  3. function isOnStudentPage() {
  4. return /jwxt\.xjzfu\.edu\.cn/i.test(window.location.href);
  5. }
  6. function parseWeekMask(mask) {
  7. if (!mask) return [];
  8. const weeks = [];
  9. for (let i = 0; i < mask.length; i++) {
  10. if (mask[i] === '1') weeks.push(i + 1);
  11. }
  12. return weeks;
  13. }
  14. function parseTeacher(str) {
  15. if (!str) return '';
  16. const names = [];
  17. const parts = str.split(';');
  18. for (const part of parts) {
  19. const sections = part.split('/');
  20. for (const section of sections) {
  21. const match = section.match(/([^[\]]+)\[主讲\]/);
  22. if (match) {
  23. names.push(match[1].trim());
  24. }
  25. }
  26. }
  27. return [...new Set(names)].join('、');
  28. }
  29. function generateTimeSlots(arrangedList) {
  30. const standardSchedule = [
  31. { number: 1, startTime: '10:00', endTime: '10:45' },
  32. { number: 2, startTime: '10:50', endTime: '11:35' },
  33. { number: 3, startTime: '11:50', endTime: '12:35' },
  34. { number: 4, startTime: '12:40', endTime: '13:25' },
  35. { number: 5, startTime: '13:30', endTime: '14:15' },
  36. { number: 6, startTime: '16:00', endTime: '16:45' },
  37. { number: 7, startTime: '16:50', endTime: '17:35' },
  38. { number: 8, startTime: '17:50', endTime: '18:35' },
  39. { number: 9, startTime: '18:40', endTime: '19:25' },
  40. { number: 10, startTime: '20:30', endTime: '21:15' },
  41. { number: 11, startTime: '21:20', endTime: '22:05' }
  42. ];
  43. const maxSection = Math.max(...arrangedList.map(c => c.endSection).filter(Boolean), 0);
  44. return standardSchedule.filter(s => s.number <= maxSection);
  45. }
  46. async function fetchScheduleData(termCode) {
  47. const body = new URLSearchParams();
  48. body.append('termCode', termCode);
  49. body.append('campusCode', '1');
  50. body.append('type', 'term');
  51. const res = await fetch(
  52. 'https://jwxt.xjzfu.edu.cn/jwapp/sys/homeapp/api/home/student/getMyScheduleDetail.do',
  53. {
  54. method: 'POST',
  55. headers: {
  56. 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
  57. 'fetch-api': 'true'
  58. },
  59. credentials: 'include',
  60. body: body.toString()
  61. }
  62. );
  63. const data = await res.json();
  64. if (data.code !== '0') throw new Error(data.msg || '获取课表失败');
  65. return data.datas;
  66. }
  67. async function fetchTermWeeks(termCode) {
  68. const res = await fetch(
  69. `https://jwxt.xjzfu.edu.cn/jwapp/sys/homeapp/api/home/getTermWeeks.do?termCode=${encodeURIComponent(termCode)}`,
  70. {
  71. headers: { 'fetch-api': 'true' },
  72. credentials: 'include'
  73. }
  74. );
  75. const data = await res.json();
  76. if (data.code !== '0') throw new Error(data.msg || '获取学期信息失败');
  77. return data.datas;
  78. }
  79. async function fetchTermList() {
  80. const res = await fetch(
  81. 'https://jwxt.xjzfu.edu.cn/jwapp/sys/homeapp/api/home/kb/xnxq.do',
  82. { headers: { 'fetch-api': 'true' }, credentials: 'include' }
  83. );
  84. const data = await res.json();
  85. if (data.code !== '0') throw new Error(data.msg || '获取学期列表失败');
  86. const datas = data.datas || [];
  87. if (datas.length === 0) throw new Error('学期列表为空');
  88. let defaultIndex = 0;
  89. const termNames = [];
  90. const termCodes = [];
  91. datas.forEach((d, i) => {
  92. termNames.push(d.itemName);
  93. termCodes.push(d.itemCode);
  94. if (d.selected === true) defaultIndex = i;
  95. });
  96. return { termNames, termCodes, defaultIndex };
  97. }
  98. async function importCourseSchedule() {
  99. try {
  100. AndroidBridge.showToast('正在获取学期列表...');
  101. const termList = await fetchTermList();
  102. let selectedIdx = termList.defaultIndex;
  103. if (typeof window.AndroidBridgePromise !== 'undefined') {
  104. const choice = await window.AndroidBridgePromise.showSingleSelection(
  105. '请选择要导入的学期',
  106. JSON.stringify(termList.termNames),
  107. termList.defaultIndex
  108. );
  109. if (choice === null) {
  110. AndroidBridge.showToast('已取消导入');
  111. return false;
  112. }
  113. selectedIdx = choice;
  114. }
  115. const termCode = termList.termCodes[selectedIdx];
  116. AndroidBridge.showToast('正在获取课表数据...');
  117. const datas = await fetchScheduleData(termCode);
  118. const arrangedList = datas.arrangedList || [];
  119. if (arrangedList.length === 0) {
  120. AndroidBridge.showToast('未找到课程数据');
  121. return false;
  122. }
  123. const courses = [];
  124. for (const item of arrangedList) {
  125. courses.push({
  126. name: item.courseName,
  127. teacher: parseTeacher(item.weeksAndTeachers),
  128. position: item.placeName || '',
  129. day: item.dayOfWeek,
  130. startSection: item.beginSection,
  131. endSection: item.endSection,
  132. weeks: parseWeekMask(item.week)
  133. });
  134. }
  135. courses.sort((a, b) => {
  136. if (a.day !== b.day) return a.day - b.day;
  137. if (a.startSection !== b.startSection) return a.startSection - b.startSection;
  138. return a.endSection - b.endSection;
  139. });
  140. console.log(`找到 ${courses.length} 门课程:`, courses);
  141. const courseResult = await window.AndroidBridgePromise.saveImportedCourses(
  142. JSON.stringify(courses)
  143. );
  144. if (courseResult !== true) {
  145. AndroidBridge.showToast('课程导入失败');
  146. return false;
  147. }
  148. AndroidBridge.showToast(`成功导入 ${courses.length} 门课程!`);
  149. const timeSlots = generateTimeSlots(arrangedList);
  150. console.log('时间段配置:', timeSlots);
  151. const slotResult = await window.AndroidBridgePromise.savePresetTimeSlots(
  152. JSON.stringify(timeSlots)
  153. );
  154. if (slotResult === true) {
  155. AndroidBridge.showToast('时间段配置成功!');
  156. }
  157. const weeksData = await fetchTermWeeks(termCode);
  158. if (weeksData && weeksData.length > 0) {
  159. const semesterStartDate = weeksData[0].startDate.split(' ')[0];
  160. const config = {
  161. semesterStartDate: semesterStartDate,
  162. semesterTotalWeeks: weeksData.length,
  163. defaultClassDuration: 45,
  164. defaultBreakDuration: 10,
  165. firstDayOfWeek: 1
  166. };
  167. await window.AndroidBridgePromise.saveCourseConfig(JSON.stringify(config));
  168. console.log('学期配置已保存:', config);
  169. }
  170. AndroidBridge.showToast('课表导入完成!');
  171. AndroidBridge.notifyTaskCompletion();
  172. return true;
  173. } catch (error) {
  174. console.error('导入过程出错:', error);
  175. AndroidBridge.showToast('导入失败: ' + error.message);
  176. return false;
  177. }
  178. }
  179. if (isOnStudentPage()) {
  180. console.log('检测到新疆政法学院教务系统');
  181. setTimeout(() => { importCourseSchedule(); }, 1000);
  182. } else {
  183. AndroidBridge.showToast('请先登录教务系统!');
  184. }