| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675 |
- // 文件: school.js
- // 长春理工大学教务系统课程表导入脚本
- // 检查是否在正确的页面
- function isOnStudentPage() {
- const url = window.location.href;
- return /jwgls[0-4]\.cust\.edu\.cn\/Student/i.test(url);
- }
- // 解析周数字符串(如 "1-8周[1-2节]" -> [1,2,3,4,5,6,7,8])
- function parseWeeks(timeStr) {
- const weeks = [];
- const weekMatch = timeStr.match(/(\d+)(?:-(\d+))?周/);
- if (weekMatch) {
- const start = parseInt(weekMatch[1]);
- const end = weekMatch[2] ? parseInt(weekMatch[2]) : start;
- for (let i = start; i <= end; i++) {
- weeks.push(i);
- }
- }
- return weeks;
- }
- // 解析节次字符串(如 "第1-2节" -> {start: 1, end: 2})
- function parseSections(sectionStr) {
- const match = sectionStr.match(/第(\d+)(?:-(\d+))?节/);
- if (match) {
- const start = parseInt(match[1]);
- const end = match[2] ? parseInt(match[2]) : start;
- return { start, end };
- }
- return null;
- }
- // 从API响应中提取并转换课程数据
- function convertScheduleData(apiData) {
- const coursesMap = new Map(); // 使用Map来临时存储和合并课程
- const timeSlots = new Set();
- // 遍历每一天
- apiData.data.AdjustDays.forEach(day => {
- const dayIndex = day.WIndex; // 1=周一, 7=周日
- // 处理所有时间段
- const allTimePieces = [
- ...(day.AM__TimePieces || []),
- ...(day.PM__TimePieces || []),
- ...(day.EV__TimePieces || [])
- ];
- allTimePieces.forEach(timePiece => {
- // 记录时间段
- if (timePiece.StartSection && timePiece.EndSection) {
- timeSlots.add(JSON.stringify({
- startSection: timePiece.StartSection,
- endSection: timePiece.EndSection,
- startTime: timePiece.StartTime,
- endTime: timePiece.EndTime
- }));
- }
- // 处理课程
- if (timePiece.Dtos && timePiece.Dtos.length > 0) {
- timePiece.Dtos.forEach(dto => {
- const content = dto.Content || [];
- // 提取课程信息
- let courseName = '';
- let teacher = [];
- let room = '';
- let weeks = [];
- let timeInfo = '';
- content.forEach(item => {
- switch(item.Key) {
- case 'Lesson':
- courseName = item.Name;
- break;
- case 'Teacher':
- teacher.push(item.Name);
- break;
- case 'Room':
- room = item.Name;
- break;
- case 'Time':
- timeInfo = item.Name;
- weeks = parseWeeks(item.Name);
- break;
- }
- });
- if (courseName && weeks.length > 0) {
- // 创建唯一键来识别相同的课程(同一天、同一课程、同一老师、同一地点、同一周次)
- const courseKey = `${dayIndex}-${courseName}-${teacher.join('、')}-${room}-${weeks.join(',')}`;
- if (coursesMap.has(courseKey)) {
- // 如果已存在,更新节次范围
- const existingCourse = coursesMap.get(courseKey);
- existingCourse.startSection = Math.min(existingCourse.startSection, timePiece.StartSection);
- existingCourse.endSection = Math.max(existingCourse.endSection, timePiece.EndSection);
- } else {
- // 如果不存在,创建新课程
- coursesMap.set(courseKey, {
- name: courseName,
- teacher: teacher.join('、'),
- position: room || '未指定',
- day: dayIndex,
- startSection: timePiece.StartSection,
- endSection: timePiece.EndSection,
- weeks: weeks
- });
- }
- }
- });
- }
- });
- });
- // 将Map转换为数组
- const courses = Array.from(coursesMap.values());
- // 按照星期和节次排序
- courses.sort((a, b) => {
- if (a.day !== b.day) return a.day - b.day;
- if (a.startSection !== b.startSection) return a.startSection - b.startSection;
- return a.endSection - b.endSection;
- });
- console.log(`合并后的课程数量: ${courses.length}`);
- return { courses, timeSlots: Array.from(timeSlots).map(s => JSON.parse(s)) };
- }
- // 获取课表数据
- async function fetchScheduleData() {
- try {
- console.log('正在获取课表数据...');
- // 构建请求参数(完整的参数结构)
- const requestData = {
- "param": "JTdCJTdE",
- "__permission": {
- "MenuID": "00000000-0000-0000-0000-000000000000",
- "Operate": "select",
- "Operation": 0
- },
- "__log": {
- "MenuID": "00000000-0000-0000-0000-000000000000",
- "Logtype": 6,
- "Context": "查询"
- }
- };
- // 获取当前域名
- const currentHost = window.location.hostname;
- const apiUrl = `https://${currentHost}/api/ClientStudent/Home/StudentHomeApi/QueryStudentScheduleData`;
- const response = await fetch(apiUrl, {
- method: 'POST',
- headers: {
- 'Accept': 'application/json, text/plain, */*',
- 'Content-Type': 'application/json;charset=UTF-8',
- 'Cache-Control': 'no-cache',
- 'Pragma': 'no-cache'
- },
- credentials: 'include',
- body: JSON.stringify(requestData)
- });
- if (!response.ok) {
- throw new Error(`HTTP error! status: ${response.status}`);
- }
- const data = await response.json();
- if (data.state !== 0) {
- throw new Error(data.message || '获取课表失败');
- }
- console.log('成功获取课表数据:', data);
- return data;
- } catch (error) {
- console.error('获取课表数据失败:', error);
- AndroidBridge.showToast('获取课表失败: ' + error.message);
- return null;
- }
- }
- // 生成时间段配置
- function generateTimeSlots(timeSlotsFromAPI) {
- const defaultTimeSlots = [
- { "number": 1, "startTime": "08:00", "endTime": "08:45" },
- { "number": 2, "startTime": "08:55", "endTime": "09:35" },
- { "number": 3, "startTime": "10:05", "endTime": "10:50" },
- { "number": 4, "startTime": "11:00", "endTime": "11:40" },
- { "number": 5, "startTime": "13:30", "endTime": "14:15" },
- { "number": 6, "startTime": "14:25", "endTime": "15:05" },
- { "number": 7, "startTime": "15:35", "endTime": "16:20" },
- { "number": 8, "startTime": "16:30", "endTime": "17:10" },
- { "number": 9, "startTime": "18:00", "endTime": "18:45" },
- { "number": 10, "startTime": "18:45", "endTime": "19:35" },
- { "number": 11, "startTime": "19:45", "endTime": "20:30" },
- { "number": 12, "startTime": "20:30", "endTime": "21:20" }
- ];
- // 如果API提供了时间信息,更新默认时间
- if (timeSlotsFromAPI && timeSlotsFromAPI.length > 0) {
- timeSlotsFromAPI.forEach(slot => {
- for (let i = slot.startSection; i <= slot.endSection; i++) {
- const timeSlot = defaultTimeSlots.find(t => t.number === i);
- if (timeSlot && i === slot.startSection) {
- timeSlot.startTime = slot.startTime;
- }
- if (timeSlot && i === slot.endSection) {
- timeSlot.endTime = slot.endTime;
- }
- }
- });
- }
- return defaultTimeSlots;
- }
- // 主函数:导入课程
- async function importCourseSchedule() {
- try {
- console.log('开始导入课程表...');
- AndroidBridge.showToast('正在获取课表数据...');
- // 获取课表数据
- const scheduleData = await fetchScheduleData();
- if (!scheduleData) {
- return false;
- }
- // 转换数据
- const { courses, timeSlots } = convertScheduleData(scheduleData);
- if (courses.length === 0) {
- AndroidBridge.showToast('未找到课程数据');
- return false;
- }
- console.log(`找到 ${courses.length} 门课程`);
- console.log('课程数据:', courses);
- // 导入课程
- const coursesResult = await window.AndroidBridgePromise.saveImportedCourses(JSON.stringify(courses));
- if (coursesResult === true) {
- console.log('课程导入成功!');
- AndroidBridge.showToast(`成功导入 ${courses.length} 门课程!`);
- } else {
- console.log('课程导入失败');
- AndroidBridge.showToast('课程导入失败');
- return false;
- }
- // 生成并导入时间段
- const finalTimeSlots = generateTimeSlots(timeSlots);
- console.log('时间段配置:', finalTimeSlots);
- const timeSlotsResult = await window.AndroidBridgePromise.savePresetTimeSlots(JSON.stringify(finalTimeSlots));
- if (timeSlotsResult === true) {
- console.log('时间段导入成功!');
- AndroidBridge.showToast('时间段配置成功!');
- } else {
- console.log('时间段导入失败');
- AndroidBridge.showToast('时间段配置失败');
- }
- return true;
- } catch (error) {
- console.error('导入过程出错:', error);
- AndroidBridge.showToast('导入失败: ' + error.message);
- return false;
- }
- }
- // ========== 以下是原有的演示函数(保留以供测试) ==========
- // 1. 显示一个公告信息弹窗
- async function demoAlert() {
- try {
- console.log("即将显示公告弹窗...");
- const confirmed = await window.AndroidBridgePromise.showAlert(
- "重要通知",
- "这是一个弹窗示例。",
- "好的"
- );
- if (confirmed) {
- console.log("用户点击了确认按钮。Alert Promise Resolved: " + confirmed);
- AndroidBridge.showToast("Alert:用户点击了确认!");
- return true; // 成功时返回 true
- } else {
- console.log("用户点击了取消按钮或关闭了弹窗。Alert Promise Resolved: " + confirmed);
- AndroidBridge.showToast("Alert:用户取消了!");
- return false; // 用户取消时返回 false
- }
- } catch (error) {
- console.error("显示公告弹窗时发生错误:", error);
- AndroidBridge.showToast("Alert:显示弹窗出错!" + error.message);
- return false; // 出现错误时也返回 false
- }
- }
- // 2. 显示带输入框的弹窗,并进行简单验证
- function validateName(name) {
- if (name === null || name.trim().length === 0) {
- return "输入不能为空!";
- }
- if (name.length < 2) {
- return "姓名至少需要2个字符!";
- }
- return false;
- }
- async function demoPrompt() {
- try {
- console.log("即将显示输入框弹窗...");
- const name = await window.AndroidBridgePromise.showPrompt(
- "输入你的姓名",
- "请输入至少2个字符",
- "测试用户",
- "validateName"
- );
- if (name !== null) {
- console.log("用户输入的姓名是: " + name);
- AndroidBridge.showToast("欢迎你," + name + "!");
- return true; // 成功时返回 true
- } else {
- console.log("用户取消了输入。");
- AndroidBridge.showToast("Prompt:用户取消了输入!");
- return false; // 用户取消时返回 false
- }
- } catch (error) {
- console.error("显示输入框弹窗时发生错误:", error);
- AndroidBridge.showToast("Prompt:显示输入框出错!" + error.message);
- return false; // 出现错误时也返回 false
- }
- }
- // 3. 显示一个单选列表弹窗
- async function demoSingleSelection() {
- const fruits = ["苹果", "香蕉", "橙子", "葡萄", "西瓜", "芒果"];
- try {
- console.log("即将显示单选列表弹窗...");
- const selectedIndex = await window.AndroidBridgePromise.showSingleSelection(
- "选择你喜欢的水果",
- JSON.stringify(fruits),
- 2
- );
- if (selectedIndex !== null && selectedIndex >= 0 && selectedIndex < fruits.length) {
- console.log("用户选择了: " + fruits[selectedIndex] + " (索引: " + selectedIndex + ")");
- AndroidBridge.showToast("你选择了 " + fruits[selectedIndex]);
- return true; // 成功时返回 true
- } else {
- console.log("用户取消了选择。");
- AndroidBridge.showToast("Single Selection:用户取消了选择!");
- return false; // 用户取消时返回 false
- }
- } catch (error) {
- console.error("显示单选列表弹窗时发生错误:", error);
- AndroidBridge.showToast("Single Selection:显示列表出错!" + error.message);
- return false; // 出现错误时也返回 false
- }
- }
- // 仍然可以使用原始的 AndroidBridge 对象
- AndroidBridge.showToast("这是一个来自 JS 的 Toast 消息,会很快消失!");
- async function demoSaveCourses() {
- // ... 代码保持不变 ...
- console.log("正在准备测试课程数据...");
- const testCourses = [
- {
- "name": "高等数学",
- "teacher": "张教授",
- "position": "教101",
- "day": 1,
- "startSection": 1,
- "endSection": 2,
- "weeks": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
- },
- {
- "name": "大学英语",
- "teacher": "李老师",
- "position": "文史楼203",
- "day": 1,
- "startSection": 2,
- "endSection": 4,
- "weeks": [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
- },
- {
- "name": "数据结构",
- "teacher": "王副教授",
- "position": "信息楼B301",
- "day": 7,
- "startSection": 2,
- "endSection": 2,
- "weeks": [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
- },
- {
- "name": "数据结构",
- "teacher": "王副教授",
- "position": "信息楼B301",
- "day": 7,
- "startSection": 3,
- "endSection": 3,
- "weeks": [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
- },
- {
- "name": "数据结构",
- "teacher": "王副教授",
- "position": "信息楼B301",
- "day": 7,
- "startSection": 4,
- "endSection": 4,
- "weeks": [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
- },
- {
- "name": "数据结构",
- "teacher": "王副教授",
- "position": "信息楼B301",
- "day": 7,
- "startSection": 5,
- "endSection": 5,
- "weeks": [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
- },
- {
- "name": "数据结构",
- "teacher": "王副教授",
- "position": "信息楼B301",
- "day": 7,
- "startSection": 6,
- "endSection": 6,
- "weeks": [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
- },
- {
- "name": "计算机组成原理",
- "teacher": "赵教授",
- "position": "实验楼401",
- "day": 4,
- "startSection": 4,
- "endSection": 4,
- "weeks": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
- },
- {
- "name": "操作系统",
- "teacher": "钱副教授",
- "position": "信息楼C205",
- "day": 5,
- "startSection": 5,
- "endSection": 5,
- "weeks": [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
- },
- {
- "name": "计算机网络",
- "teacher": "孙教授",
- "position": "信息楼D103",
- "day": 6,
- "startSection": 6,
- "endSection": 6,
- "weeks": [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
- },
- {
- "name": "软件工程",
- "teacher": "周副教授",
- "position": "创新楼301",
- "day": 7,
- "startSection": 7,
- "endSection": 7,
- "weeks": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
- },
- {
- "name": "数据库原理",
- "teacher": "吴教授",
- "position": "信息楼E201",
- "day": 1,
- "startSection": 8,
- "endSection": 8,
- "weeks": [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
- },
- {
- "name": "人工智能",
- "teacher": "郑副教授",
- "position": "智能楼101",
- "day": 2,
- "startSection": 9,
- "endSection": 9,
- "weeks": [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
- },
- {
- "name": "机器学习",
- "teacher": "冯教授",
- "position": "智能楼203",
- "day": 3,
- "startSection": 10,
- "endSection": 10,
- "weeks": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
- },
- {
- "name": "编译原理",
- "teacher": "陈副教授",
- "position": "信息楼F105",
- "day": 4,
- "startSection": 11,
- "endSection": 11,
- "weeks": [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
- },
- {
- "name": "计算机图形学",
- "teacher": "褚教授",
- "position": "图形楼301",
- "day": 5,
- "startSection": 12,
- "endSection": 12,
- "weeks": [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
- },
- {
- "name": "网络安全",
- "teacher": "卫副教授",
- "position": "安全楼201",
- "day": 6,
- "startSection": 13,
- "endSection": 13,
- "weeks": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
- },
- {
- "name": "分布式系统",
- "teacher": "蒋教授",
- "position": "云楼101",
- "day": 7,
- "startSection": 14,
- "endSection": 14,
- "weeks": [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
- },
- {
- "name": "大数据技术",
- "teacher": "沈副教授",
- "position": "数据楼301",
- "day": 1,
- "startSection": 15,
- "endSection": 15,
- "weeks": [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
- },
- {
- "name": "物联网技术",
- "teacher": "韩教授",
- "position": "物联楼201",
- "day": 2,
- "startSection": 16,
- "endSection": 16,
- "weeks": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
- }
- ];
- try {
- console.log("正在尝试导入课程...");
- const result = await window.AndroidBridgePromise.saveImportedCourses(JSON.stringify(testCourses));
- if (result === true) {
- console.log("课程导入成功!");
- AndroidBridge.showToast("测试课程导入成功!");
- } else {
- console.log("课程导入未成功,结果:" + result);
- AndroidBridge.showToast("测试课程导入失败,请查看日志。");
- }
- } catch (error) {
- console.error("导入课程时发生错误:", error);
- AndroidBridge.showToast("导入课程失败: " + error.message);
- }
- }
- // 5. 导入预设时间段(保持不变)
- async function importPresetTimeSlots() {
- console.log("正在准备预设时间段数据...");
- const presetTimeSlots = [
- { "number": 1, "startTime": "08:00", "endTime": "08:01" },
- { "number": 2, "startTime": "09:00", "endTime": "09:01" },
- { "number": 3, "startTime": "10:00", "endTime": "10:01" },
- { "number": 4, "startTime": "11:00", "endTime": "11:01" },
- { "number": 5, "startTime": "12:00", "endTime": "12:01" },
- { "number": 6, "startTime": "13:00", "endTime": "13:01" },
- { "number": 7, "startTime": "14:00", "endTime": "14:01" },
- { "number": 8, "startTime": "15:00", "endTime": "15:01" },
- { "number": 9, "startTime": "16:00", "endTime": "16:01" },
- { "number": 10, "startTime": "17:00", "endTime": "17:01" },
- { "number": 11, "startTime": "18:00", "endTime": "18:01" },
- { "number": 12, "startTime": "19:00", "endTime": "19:01" },
- { "number": 13, "startTime": "20:00", "endTime": "20:01" },
- { "number": 14, "startTime": "21:00", "endTime": "21:01" },
- { "number": 15, "startTime": "22:00", "endTime": "22:01" },
- { "number": 16, "startTime": "23:00", "endTime": "23:01" }
- ];
- try {
- console.log("正在尝试导入预设时间段...");
- const result = await window.AndroidBridgePromise.savePresetTimeSlots(JSON.stringify(presetTimeSlots));
- if (result === true) {
- console.log("预设时间段导入成功!");
- window.AndroidBridge.showToast("测试时间段导入成功!");
- } else {
- console.log("预设时间段导入未成功,结果:" + result);
- window.AndroidBridge.showToast("测试时间段导入失败,请查看日志。");
- }
- } catch (error) {
- console.error("导入时间段时发生错误:", error);
- window.AndroidBridge.showToast("导入时间段失败: " + error.message);
- }
- }
- /**
- * 编排这些异步操作,并在用户取消时停止后续执行。
- */
- async function runAllDemosSequentially() {
- AndroidBridge.showToast("所有演示将按顺序开始...");
- // 1. 运行第一个演示:Alert
- const alertResult = await demoAlert();
- if (!alertResult) {
- console.log("用户取消了 Alert 演示,停止后续执行。");
- return; // 用户取消,立即退出函数
- }
- // 2. 运行第二个演示:Prompt
- const promptResult = await demoPrompt();
- if (!promptResult) {
- console.log("用户取消了 Prompt 演示,停止后续执行。");
- return; // 用户取消,立即退出函数
- }
- // 3. 运行第三个演示:SingleSelection
- const selectionResult = await demoSingleSelection();
- if (!selectionResult) {
- console.log("用户取消了 Single Selection 演示,停止后续执行。");
- return; // 用户取消,立即退出函数
- }
- console.log("所有弹窗演示已完成。");
- AndroidBridge.showToast("所有弹窗演示已完成!");
- // 以下是数据导入,与用户交互无关,可以继续
- await demoSaveCourses();
- await importPresetTimeSlots();
- // 发送最终的生命周期完成信号
- AndroidBridge.notifyTaskCompletion();
- }
- // ========== 主执行逻辑 ==========
- // 检查页面并执行相应操作
- if (isOnStudentPage()) {
- console.log('检测到在长春理工大学教务系统学生页面');
- AndroidBridge.showToast('正在准备导入课程表...');
- // 延迟一秒确保页面加载完成
- setTimeout(async () => {
- const success = await importCourseSchedule();
- if (success) {
- AndroidBridge.notifyTaskCompletion();
- }
- }, 1000);
- } else {
- console.log('当前不在教务系统页面,运行演示模式');
- AndroidBridge.showToast('请先登录教务系统!');
- // 可选:运行演示
- const runDemo = false; // 设为true可以运行演示
- if (runDemo) {
- runAllDemosSequentially();
- }
- }
|