| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- // 文件: guilin_medical.js
- // 功能:从桂医教务系统获取课程表,通过桥接 API 导入到拾光课程表
- // ---------- 全局验证函数 ----------
- function validateYearInput(input) {
- if (/^\d{4}$/.test(input)) {
- return false; // 验证通过
- } else {
- return "请输入四位数字的年份(例如 2024)";
- }
- }
- // ---------- 工具函数 ----------
- function parseWeeks(weeksStr) {
- weeksStr = weeksStr.replace('周', '');
- const parts = weeksStr.split(',');
- const weeks = [];
- for (const part of parts) {
- if (part.includes('-')) {
- const [start, end] = part.split('-').map(Number);
- for (let i = start; i <= end; i++) weeks.push(i);
- } else {
- weeks.push(Number(part));
- }
- }
- return weeks;
- }
- function parseSections(jcdm) {
- const str = String(jcdm);
- const sections = [];
- if (str.includes('-')) {
- const [start, end] = str.split('-').map(Number);
- for (let i = start; i <= end; i++) sections.push(i);
- } else if (/^\d+$/.test(str)) {
- for (let i = 0; i < str.length; i += 2) {
- const sec = parseInt(str.substring(i, i + 2), 10);
- if (!isNaN(sec)) sections.push(sec);
- }
- } else {
- sections.push(parseInt(str));
- }
- return sections;
- }
- function parseRawCourses(rawData) {
- const courseInfos = [];
- for (const course of rawData) {
- const name = course.kcmc;
- const teacher = course.teaxms;
- const position = course.jxcdmc;
- const weeks = parseWeeks(course.zc);
- const day = parseInt(course.xq);
- const sections = parseSections(course.jcdm);
- courseInfos.push({ name, teacher, position, weeks, day, sections });
- }
- return courseInfos;
- }
- function convertToTargetCourses(middleCourses) {
- return middleCourses.map(c => ({
- name: c.name,
- teacher: c.teacher,
- position: c.position,
- day: c.day,
- startSection: c.sections[0],
- endSection: c.sections[c.sections.length - 1],
- weeks: c.weeks,
- isCustomTime: false
- }));
- }
- function getTimeSlots() {
- return [
- { number: 1, startTime: "08:30", endTime: "09:10" },
- { number: 2, startTime: "09:20", endTime: "10:00" },
- { number: 3, startTime: "10:10", endTime: "10:50" },
- { number: 4, startTime: "11:00", endTime: "11:40" },
- { number: 5, startTime: "11:50", endTime: "12:30" },
- { number: 6, startTime: "14:30", endTime: "15:10" },
- { number: 7, startTime: "15:20", endTime: "16:00" },
- { number: 8, startTime: "16:10", endTime: "16:50" },
- { number: 9, startTime: "17:00", endTime: "17:40" },
- { number: 10, startTime: "19:00", endTime: "19:40" },
- { number: 11, startTime: "19:50", endTime: "20:30" },
- { number: 12, startTime: "20:40", endTime: "21:20" }
- ];
- }
- // ---------- 网络请求 ----------
- async function fetchCourseData(xnxqdm) {
- let page = 1;
- const rowsPerPage = 100;
- let allRows = [];
- let total = 0;
- while (true) {
- const res = await fetch("https://ejwc.glmu.edu.cn/xsgrkbcx!getDataList.action", {
- headers: {
- "accept": "application/json, text/javascript, */*; q=0.01",
- "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
- "x-requested-with": "XMLHttpRequest"
- },
- body: `xnxqdm=${xnxqdm}&page=${page}&rows=${rowsPerPage}`,
- method: "POST",
- credentials: "include"
- });
- if (!res.ok) {
- throw new Error(`HTTP ${res.status}: ${res.statusText}`);
- }
- const ret = await res.json();
- if (!ret.rows || !Array.isArray(ret.rows)) {
- throw new Error("返回数据格式不正确");
- }
- total = ret.total;
- allRows = allRows.concat(ret.rows);
- if (allRows.length >= total) break;
- page++;
- if (page > 10) break;
- }
- return allRows;
- }
- // ---------- 用户交互 ----------
- async function promptUserToStart() {
- return await window.AndroidBridgePromise.showAlert(
- "重要提醒",
- "请确保您已登录桂医教务系统,且当前页面为教务系统内任意页面。\n\n点击确定继续。",
- "确定"
- );
- }
- async function getAcademicYear() {
- return await window.AndroidBridgePromise.showPrompt(
- "学年设置",
- "请输入本学年开始的年份(例如 2024)",
- "2024",
- "validateYearInput" // 传入验证函数名
- );
- }
- async function selectSemester() {
- const semesterOptions = ["上学期", "下学期", "短学期"];
- const index = await window.AndroidBridgePromise.showSingleSelection(
- "选择学期",
- JSON.stringify(semesterOptions),
- 0
- );
- if (index === null || index < 0) return null;
- return index;
- }
- // ---------- 主流程 ----------
- async function run() {
- try {
- // 1. 公告
- const confirmed = await promptUserToStart();
- if (!confirmed) {
- AndroidBridge.showToast("用户取消了导入流程。");
- return;
- }
- // 2. 获取学年
- const yearInput = await getAcademicYear();
- if (yearInput === null) {
- AndroidBridge.showToast("导入已取消。");
- return;
- }
- const yearNum = parseInt(yearInput);
- if (isNaN(yearNum) || yearNum < 2000 || yearNum > 2100) {
- await window.AndroidBridgePromise.showAlert("错误", "学年输入无效,请输入2000-2100之间的数字。", "确定");
- return;
- }
- // 3. 获取学期
- const semesterIndex = await selectSemester();
- if (semesterIndex === null) {
- AndroidBridge.showToast("导入已取消。");
- return;
- }
- const termCode = semesterIndex === 0 ? "01" : (semesterIndex === 1 ? "02" : "03");
- const xnxqdm = `${yearNum}${termCode}`;
- // 4. 请求课表
- AndroidBridge.showToast("正在获取课表,请稍候...");
- let rawData;
- try {
- rawData = await fetchCourseData(xnxqdm);
- } catch (fetchErr) {
- await window.AndroidBridgePromise.showAlert(
- "网络请求失败",
- `请求教务系统失败:${fetchErr.message}\n\n请检查网络连接和登录状态。`,
- "确定"
- );
- return;
- }
- if (!rawData.length) {
- await window.AndroidBridgePromise.showAlert("提示", "未获取到任何课程数据。请确认已登录教务系统并选择正确的学年学期。", "确定");
- return;
- }
- // 5. 解析并转换
- const middleCourses = parseRawCourses(rawData);
- const targetCourses = convertToTargetCourses(middleCourses);
- // 6. 保存课程
- try {
- await window.AndroidBridgePromise.saveImportedCourses(JSON.stringify(targetCourses));
- AndroidBridge.showToast(`课程数据已导入(共 ${targetCourses.length} 条)`);
- } catch (saveErr) {
- await window.AndroidBridgePromise.showAlert("保存课程失败", saveErr.message, "确定");
- return;
- }
- // 7. 保存时间段
- const timeSlots = getTimeSlots();
- try {
- await window.AndroidBridgePromise.savePresetTimeSlots(JSON.stringify(timeSlots));
- AndroidBridge.showToast("时间段数据已导入");
- } catch (slotErr) {
- // 时间段保存失败不终止流程,只提示
- AndroidBridge.showToast(`时间段保存失败:${slotErr.message}`);
- }
- // 8. 完成通知
- AndroidBridge.showToast("导入完成!");
- AndroidBridge.notifyTaskCompletion();
- } catch (err) {
- // 捕获所有未预料的错误
- console.error("run error:", err);
- await window.AndroidBridgePromise.showAlert(
- "导入失败",
- `未知错误:${err.message || err}\n\n请联系开发者。`,
- "确定"
- );
- // 仍然通知完成,但可能不会生成有效文件
- AndroidBridge.notifyTaskCompletion();
- }
- }
- // 启动
- run();
|