| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- // 大连工程学院教务系统(jw.dlutci.edu.cn)拾光课表导入适配脚本
- // 基于智慧教务(app)系统,接口为 xskcb.do 获取课表、xnxqcx.do 选择学期
- // 大连工程学院作息时间表(第1-12节)
- const DLUTCI_TIME_SLOTS = [
- { number: 1, startTime: "08:10", endTime: "08:55" },
- { number: 2, startTime: "09:00", endTime: "09:45" },
- { number: 3, startTime: "10:15", endTime: "11:00" },
- { number: 4, startTime: "11:05", endTime: "11:50" },
- { number: 5, startTime: "13:20", endTime: "14:05" },
- { number: 6, startTime: "14:10", endTime: "14:55" },
- { number: 7, startTime: "15:15", endTime: "16:00" },
- { number: 8, startTime: "16:00", endTime: "16:45" },
- { number: 9, startTime: "17:45", endTime: "18:30" },
- { number: 10, startTime: "18:30", endTime: "19:15" },
- { number: 11, startTime: "19:35", endTime: "20:20" },
- { number: 12, startTime: "20:20", endTime: "21:05" }
- ];
- // 周次位图解析:SKZC 为"0"/"1"串,第 i 位为"1"表示第 i+1 周有课
- function parseWeeks(skzc) {
- const value = String(skzc || "");
- const weeks = [];
- for (let i = 0; i < value.length; i++) {
- if (value[i] === "1") weeks.push(i + 1);
- }
- return weeks;
- }
- function getErrorMessage(error) {
- if (error && typeof error.message === "string" && error.message.trim()) return error.message;
- if (typeof error === "string" && error.trim()) return error;
- try {
- const serialized = JSON.stringify(error);
- if (serialized && serialized !== "{}") return serialized;
- } catch (_) {
- // Ignore serialization failures.
- }
- return "未知错误";
- }
- // 教室:JASMC 为主,XXXQDM_DISPLAY 校区做后缀;均无则"待定"
- function parsePosition(row) {
- const campus = String(row.XXXQDM_DISPLAY || "").trim();
- const room = String(row.JASMC || "").trim();
- if (campus && room) return `${room}(${campus})`;
- return room || campus || "待定";
- }
- function parseCourse(row) {
- const day = Number(row.SKXQ);
- const startSection = Number(row.KSJC);
- const endSection = Number(row.JSJC);
- const weeks = parseWeeks(row.SKZC);
- if (!row.KCM || !day || day < 1 || day > 7 || !startSection || !endSection ||
- startSection > endSection || weeks.length === 0) return null;
- return {
- name: String(row.KCM).trim(),
- teacher: String(row.SKJS || "").split(/[\\/、,,]/)[0].trim() || "未知",
- position: parsePosition(row),
- day,
- startSection,
- endSection,
- weeks
- };
- }
- // 接口返回 JSON = { datas: { xskcb: { rows: [...] } } },按行为一门课;同一门课多处时段会分多条,按组合键去重
- function transformSchedule(payload) {
- const rows = payload && payload.datas && payload.datas.xskcb && payload.datas.xskcb.rows;
- if (!Array.isArray(rows)) return [];
- const rawCourses = rows.map(parseCourse).filter(Boolean);
- const seen = new Set();
- const courses = [];
- for (const c of rawCourses) {
- const key = `${c.name}|${c.day}|${c.startSection}|${c.endSection}|${c.weeks.join(',')}|${c.teacher}|${c.position}`;
- if (seen.has(key)) continue;
- seen.add(key);
- courses.push(c);
- }
- return courses;
- }
- // 判断是否登录页
- function isLoginPage() {
- const url = window.location.href;
- return /login/i.test(url);
- }
- async function fetchCurrentSemester() {
- const response = await fetch("/jwapp/sys/wdkb/modules/jshkcb/dqxnxq.do", {
- method: "POST",
- headers: {
- "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
- "X-Requested-With": "XMLHttpRequest"
- },
- body: "",
- credentials: "include"
- });
- if (!response.ok) throw new Error(`当前学期接口请求失败(HTTP ${response.status})`);
- const payload = await response.json();
- const rows = payload && payload.datas && payload.datas.dqxnxq && payload.datas.dqxnxq.rows;
- const term = Array.isArray(rows) && rows.length > 0 ? rows[0] : null;
- if (!term || (!term.DM && !term.XNXQDM)) throw new Error("未获取到当前学期信息。");
- return { code: String(term.XNXQDM || term.DM) };
- }
- async function fetchSemesterList() {
- const response = await fetch("/jwapp/sys/wdkb/modules/jshkcb/xnxqcx.do", {
- method: "POST",
- headers: {
- "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
- "X-Requested-With": "XMLHttpRequest"
- },
- body: "*order=-DM",
- credentials: "include"
- });
- if (!response.ok) throw new Error(`学期列表接口请求失败(HTTP ${response.status})`);
- const payload = await response.json();
- const rows = payload && payload.datas && payload.datas.xnxqcx && payload.datas.xnxqcx.rows;
- if (!Array.isArray(rows)) throw new Error("学期列表返回数据格式异常。");
- return rows.filter(item => item && (item.DM || item.XNXQDM)).map(item => {
- const code = String(item.XNXQDM || item.DM);
- const MC = String(item.MC || item.DM || item.XNXQDM);
- return { code, name: MC };
- });
- }
- // 选择学期,默认定位到当前学期
- async function selectSemester() {
- const current = await fetchCurrentSemester();
- const list = await fetchSemesterList();
- if (list.length === 0) throw new Error("未获取到学期列表。");
- const defaultIndex = Math.max(0, list.findIndex(s => s.code === current.code));
- const selectedIndex = await window.shiguangBridgePromise.showSingleSelection(
- "请选择学期",
- JSON.stringify(list.map(s => s.name)),
- defaultIndex
- );
- if (selectedIndex === null || selectedIndex === undefined) return null;
- return list[selectedIndex];
- }
- async function fetchCourses(xnxqdm) {
- window.shiguangBridge.showToast("正在请求课表数据...");
- // 请求参数仅传 XNXQDM,即可返回该学期全部课表
- const response = await fetch("/jwapp/sys/wdkb/modules/xskcb/xskcb.do", {
- method: "POST",
- headers: {
- "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
- "X-Requested-With": "XMLHttpRequest"
- },
- body: `XNXQDM=${encodeURIComponent(xnxqdm)}`,
- credentials: "include"
- });
- if (!response.ok) throw new Error(`课表接口请求失败(HTTP ${response.status})`);
- const payload = await response.json();
- return transformSchedule(payload);
- }
- // 保存预设作息时间(失败仅告警,不阻断课程导入)
- async function saveTimeSlots(timeSlots) {
- if (!timeSlots || timeSlots.length === 0) return;
- try {
- await window.shiguangBridgePromise.savePresetTimeSlots(JSON.stringify(timeSlots));
- console.log("JS: 作息时间保存成功");
- } catch (error) {
- console.error("JS: 作息时间保存失败:", error);
- }
- }
- async function runImportFlow() {
- if (isLoginPage()) {
- window.shiguangBridge.showToast("导入失败:请先登录教务系统!");
- return;
- }
- const alertConfirmed = await window.shiguangBridgePromise.showAlert(
- "教务系统课表导入",
- "导入前请确保您已登录教务系统,建议在课表页面进行导入",
- "好的,开始导入"
- );
- if (!alertConfirmed) {
- window.shiguangBridge.showToast("用户取消了导入。");
- return;
- }
- try {
- const semester = await selectSemester();
- if (!semester) {
- window.shiguangBridge.showToast("用户取消了导入。");
- return;
- }
- console.log(`JS: 选择学期: ${semester.name} (${semester.code})`);
- const courses = await fetchCourses(semester.code);
- if (courses.length === 0) {
- window.shiguangBridge.showToast("未找到任何课程数据,请检查所选学期是否正确。");
- return;
- }
- window.shiguangBridge.showToast(`正在保存 ${courses.length} 门课程...`);
- await window.shiguangBridgePromise.saveImportedCourses(JSON.stringify(courses, null, 2));
- await saveTimeSlots(DLUTCI_TIME_SLOTS);
- window.shiguangBridge.showToast(`课程导入成功,共导入 ${courses.length} 门课程!`);
- window.shiguangBridge.notifyTaskCompletion();
- } catch (error) {
- window.shiguangBridge.showToast(`导入失败:${getErrorMessage(error)}`);
- console.error("JS: Import Error:", error);
- }
- }
- runImportFlow();
|