sddfvc.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // 山东药品食品职业学院(sddfvc.edu.cn) 拾光课程表适配脚本
  2. // 非该大学开发者适配,开发者无法及时发现问题
  3. // 出现问题请提联系开发者或者提交pr更改,这更加快速
  4. // 数据解析函数
  5. /**
  6. * 将周次字符串结合单双周标识解析为数字数组
  7. * @param {string} zcString "7-15,17-20"
  8. * @param {number} dsz 0: 全周, 1: 单周, 2: 双周, -1: 全周
  9. */
  10. function parseWeeks(zcString, dsz) {
  11. let weeks = [];
  12. if (!zcString) return weeks;
  13. // 解析基础周次
  14. zcString.split(',').forEach(part => {
  15. if (part.includes('-')) {
  16. const [start, end] = part.split('-').map(Number);
  17. for (let i = start; i <= end; i++) weeks.push(i);
  18. } else {
  19. weeks.push(Number(part));
  20. }
  21. });
  22. // 处理单双周过滤
  23. if (dsz === 1) {
  24. weeks = weeks.filter(w => w % 2 !== 0);
  25. } else if (dsz === 2) {
  26. weeks = weeks.filter(w => w % 2 === 0);
  27. }
  28. return weeks;
  29. }
  30. /**
  31. * 转换课程格式为应用模型
  32. */
  33. function parseCoursesToModel(sourceData) {
  34. const resultCourses = [];
  35. const days = ["xq1", "xq2", "xq3", "xq4", "xq5", "xq6", "xq7"];
  36. const sectionMap = { "1": 1, "3": 2, "5": 3, "7": 4 };
  37. days.forEach((dayKey, index) => {
  38. const dayContent = sourceData[dayKey];
  39. if (!dayContent) return;
  40. Object.keys(dayContent).forEach(slotNum => {
  41. const mappedSection = sectionMap[slotNum];
  42. if (!mappedSection) return;
  43. Object.values(dayContent[slotNum]).forEach(item => {
  44. const courseName = item.skbj[0][1];
  45. Object.values(item.pkmx).forEach(detail => {
  46. if (!detail) return;
  47. const computedWeeks = parseWeeks(detail.zc.zc, detail.zc.dsz);
  48. if (computedWeeks.length === 0) return;
  49. resultCourses.push({
  50. "name": courseName,
  51. "teacher": detail.teacher[0]?.xm || "未知教师",
  52. "position": detail.classroom || "未知地点",
  53. "day": index + 1,
  54. "startSection": mappedSection,
  55. "endSection": mappedSection,
  56. "weeks": computedWeeks
  57. });
  58. });
  59. });
  60. });
  61. });
  62. return resultCourses;
  63. }
  64. // 网络与交互业务函数
  65. /**
  66. * 保存课表全局配置
  67. */
  68. async function saveAppConfig() {
  69. const config = {
  70. "semesterTotalWeeks": 22,
  71. "defaultClassDuration": 90,
  72. "defaultBreakDuration": 15,
  73. "firstDayOfWeek": 1
  74. };
  75. return await window.AndroidBridgePromise.saveCourseConfig(JSON.stringify(config));
  76. }
  77. /**
  78. * 保存时间段配置
  79. */
  80. async function saveAppTimeSlots() {
  81. const timeSlots = [
  82. { "number": 1, "startTime": "08:30", "endTime": "10:00" },
  83. { "number": 2, "startTime": "10:15", "endTime": "11:45" },
  84. { "number": 3, "startTime": "13:30", "endTime": "15:00" },
  85. { "number": 4, "startTime": "15:15", "endTime": "16:45" }
  86. ];
  87. return await window.AndroidBridgePromise.savePresetTimeSlots(JSON.stringify(timeSlots));
  88. }
  89. /**
  90. * 获取并让用户选择学期 ID
  91. */
  92. async function getSelectedSemesterId(apiToken) {
  93. const xqRes = await fetch(`http://jwxt.sddfvc.edu.cn/mobile/student/mobile_kcb_xq?api_token=${apiToken}`);
  94. const xqJson = await xqRes.json();
  95. const xqList = xqJson.data.xq_all;
  96. const currentXq = xqJson.data.xq_current;
  97. const xqNames = xqList.map(item => item.xqmc);
  98. const defaultIdx = xqList.findIndex(item => item.id === currentXq.id);
  99. const selectedIdx = await window.AndroidBridgePromise.showSingleSelection(
  100. "请确认导入学期",
  101. JSON.stringify(xqNames),
  102. defaultIdx !== -1 ? defaultIdx : xqNames.length - 1
  103. );
  104. return selectedIdx !== null ? xqList[selectedIdx].id : null;
  105. }
  106. // 流程控制
  107. async function runImportFlow() {
  108. try {
  109. const tokenMatch = document.cookie.match(/api_token=([^;]+)/);
  110. if (!tokenMatch) {
  111. AndroidBridge.showToast("未检测到登录状态,请先登录");
  112. return;
  113. }
  114. const apiToken = tokenMatch[1];
  115. const semesterId = await getSelectedSemesterId(apiToken);
  116. if (!semesterId) {
  117. AndroidBridge.showToast("导入已取消");
  118. return;
  119. }
  120. AndroidBridge.showToast("正在获取课表数据...");
  121. const kcbRes = await fetch(`http://jwxt.sddfvc.edu.cn/mobile/student/mobile_kcb?api_token=${apiToken}&xq=${semesterId}`);
  122. const kcbJson = await kcbRes.json();
  123. const finalCourses = parseCoursesToModel(kcbJson.data);
  124. if (finalCourses.length === 0) {
  125. AndroidBridge.showToast("该学期暂无课程");
  126. return;
  127. }
  128. AndroidBridge.showToast("正在保存配置...");
  129. await saveAppConfig();
  130. await saveAppTimeSlots();
  131. await window.AndroidBridgePromise.saveImportedCourses(JSON.stringify(finalCourses));
  132. AndroidBridge.showToast(`成功导入 ${finalCourses.length} 条课程明细`);
  133. AndroidBridge.notifyTaskCompletion();
  134. } catch (error) {
  135. console.error(error);
  136. AndroidBridge.showToast("异常: " + error.message);
  137. }
  138. }
  139. runImportFlow();