starlink.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /**
  2. * 星链课表分享导入脚本
  3. */
  4. // 输入验证
  5. function validateInput(input) {
  6. if (!input || input.trim().length === 0) return "请输入分享码!";
  7. return false;
  8. }
  9. // 提取分享码
  10. function extractShareCode(text) {
  11. const structuredRegex = /输入:\s*([^(\s]+)/;
  12. const fallbackRegex = /([a-zA-Z0-9-]{5,20})/;
  13. const matchA = text.match(structuredRegex);
  14. if (matchA && matchA[1]) return matchA[1].trim();
  15. const matchB = text.match(fallbackRegex);
  16. if (matchB) return matchB[1].trim();
  17. return text.trim();
  18. }
  19. // 课程去重与合并
  20. function processAndMergeCourses(courses) {
  21. if (!courses || courses.length === 0) return [];
  22. // 排序:星期 > 课程名 > 教师 > 教室 > 周次 > 起始节次
  23. courses.sort((a, b) =>
  24. a.day - b.day ||
  25. (a.name || "").localeCompare(b.name || "") ||
  26. (a.teacher || "").localeCompare(b.teacher || "") ||
  27. (a.position || "").localeCompare(b.position || "") ||
  28. JSON.stringify(a.weeks).localeCompare(JSON.stringify(b.weeks)) ||
  29. a.startSection - b.startSection
  30. );
  31. const mergedResults = [];
  32. courses.forEach(current => {
  33. if (mergedResults.length === 0) {
  34. mergedResults.push(current);
  35. return;
  36. }
  37. const last = mergedResults[mergedResults.length - 1];
  38. // 完全重复过滤
  39. const isDuplicate =
  40. last.day === current.day &&
  41. last.name === current.name &&
  42. last.teacher === current.teacher &&
  43. last.position === current.position &&
  44. last.startSection === current.startSection &&
  45. last.endSection === current.endSection &&
  46. JSON.stringify(last.weeks) === JSON.stringify(current.weeks);
  47. if (isDuplicate) return;
  48. // 连堂课合并
  49. const canMerge =
  50. last.day === current.day &&
  51. last.name === current.name &&
  52. last.teacher === current.teacher &&
  53. last.position === current.position &&
  54. JSON.stringify(last.weeks) === JSON.stringify(current.weeks) &&
  55. current.startSection <= last.endSection + 1;
  56. if (canMerge) {
  57. last.endSection = Math.max(last.endSection, current.endSection);
  58. } else {
  59. mergedResults.push(current);
  60. }
  61. });
  62. return mergedResults;
  63. }
  64. // 主程序
  65. async function runStarlinkImport() {
  66. try {
  67. const userInput = await window.AndroidBridgePromise.showPrompt(
  68. "导入星链课表",
  69. "请粘贴分享文案(包含分享码)",
  70. "",
  71. "validateInput"
  72. );
  73. if (!userInput) return;
  74. const shareCode = extractShareCode(userInput);
  75. const apiUrl = `https://api.starlinkkb.cn/share/curriculum/${shareCode}`;
  76. AndroidBridge.showToast("正在同步云端数据...");
  77. const response = await fetch(apiUrl);
  78. if (!response.ok) throw new Error("分享码已失效或网络异常");
  79. const resJson = await response.json();
  80. const data = resJson.data;
  81. // 数据映射
  82. const rawCourses = data.courses.map(c => ({
  83. name: c.name,
  84. teacher: (c.teacher && c.teacher !== "无") ? c.teacher : "未知",
  85. position: (c.location && c.location.replace(/^@/, '').trim() !== "")
  86. ? c.location.replace(/^@/, '').trim()
  87. : "未排地点",
  88. day: c.weekday,
  89. startSection: c.startSection,
  90. endSection: c.endSection,
  91. weeks: c.weeks
  92. }));
  93. const finalCourses = processAndMergeCourses(rawCourses);
  94. const config = {
  95. semesterStartDate: data.startDate ? data.startDate.substring(0, 10) : null,
  96. semesterTotalWeeks: data.totalWeeks || 20
  97. };
  98. await window.AndroidBridgePromise.saveCourseConfig(JSON.stringify(config));
  99. const success = await window.AndroidBridgePromise.saveImportedCourses(JSON.stringify(finalCourses));
  100. if (success) {
  101. AndroidBridge.showToast("导入成功!");
  102. AndroidBridge.notifyTaskCompletion();
  103. }
  104. } catch (e) {
  105. await window.AndroidBridgePromise.showAlert("导入失败", e.message, "确定");
  106. }
  107. }
  108. runStarlinkImport();