| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420 |
- // 山东华宇工学院 拾光课程表适配脚本
- // 基于正方教务系统API适配
- /**
- * 解析周次字符串
- */
- function parseWeeks(weekStr) {
- var weeks = [];
- if (!weekStr) return weeks;
-
- var weekSets = weekStr.split(',');
- for (var i = 0; i < weekSets.length; i++) {
- var set = weekSets[i].trim();
- var isSingle = set.indexOf('(单)') !== -1;
- var isDouble = set.indexOf('(双)') !== -1;
-
- set = set.split('(单)').join('');
- set = set.split('(双)').join('');
- set = set.trim();
-
- var dashIdx = set.indexOf('-');
- var start = 0;
- var end = 0;
- var processed = false;
-
- if (dashIdx !== -1 && set.indexOf('周') !== -1) {
- start = parseInt(set.substring(0, dashIdx));
- var endPart = set.substring(dashIdx + 1);
- endPart = endPart.split('周').join('');
- end = parseInt(endPart);
- processed = true;
- } else {
- var weekNum = parseInt(set);
- if (!isNaN(weekNum)) {
- start = end = weekNum;
- processed = true;
- }
- }
-
- if (processed) {
- for (var w = start; w <= end; w++) {
- if (isSingle && w % 2 === 0) continue;
- if (isDouble && w % 2 !== 0) continue;
- weeks.push(w);
- }
- }
- }
-
- var uniqueWeeks = [];
- for (var j = 0; j < weeks.length; j++) {
- if (uniqueWeeks.indexOf(weeks[j]) === -1) {
- uniqueWeeks.push(weeks[j]);
- }
- }
- uniqueWeeks.sort(function(a, b) { return a - b; });
- return uniqueWeeks;
- }
- /**
- * 解析API返回的JSON数据
- */
- function parseJsonData(jsonData) {
- console.log('JS: parseJsonData 正在解析JSON数据...');
-
- if (!jsonData || !Array.isArray(jsonData.kbList)) {
- console.warn('JS: JSON数据结构错误或缺少kbList字段');
- return [];
- }
-
- var rawCourseList = jsonData.kbList;
- var finalCourseList = [];
-
- for (var i = 0; i < rawCourseList.length; i++) {
- var rawCourse = rawCourseList[i];
-
- if (!rawCourse.kcmc || !rawCourse.xm || !rawCourse.cdmc ||
- !rawCourse.xqj || !rawCourse.jcs || !rawCourse.zcd) {
- continue;
- }
-
- var weeksArray = parseWeeks(rawCourse.zcd);
- if (weeksArray.length === 0) {
- continue;
- }
-
- var sectionParts = rawCourse.jcs.split('-');
- var startSection = parseInt(sectionParts[0]);
- var endSection = parseInt(sectionParts[sectionParts.length - 1]);
- var day = parseInt(rawCourse.xqj);
-
- if (isNaN(day) || isNaN(startSection) || isNaN(endSection) ||
- day < 1 || day > 7 || startSection > endSection) {
- continue;
- }
-
- var courseName = rawCourse.kcmc.trim();
- courseName = courseName.split('★').join('');
- courseName = courseName.split('●').join('');
- courseName = courseName.split('◆').join('');
- courseName = courseName.split('◇').join('');
- courseName = courseName.split('○').join('');
-
- finalCourseList.push({
- name: courseName,
- teacher: rawCourse.xm.trim(),
- position: rawCourse.cdmc.trim(),
- day: day,
- startSection: startSection,
- endSection: endSection,
- weeks: weeksArray
- });
- }
-
- finalCourseList.sort(function(a, b) {
- if (a.day !== b.day) return a.day - b.day;
- if (a.startSection !== b.startSection) return a.startSection - b.startSection;
- return a.name.localeCompare(b.name);
- });
-
- console.log('JS: JSON数据解析完成,共找到 ' + finalCourseList.length + ' 门课程');
- return finalCourseList;
- }
- /**
- * 检查是否在登录页面
- */
- function isLoginPage() {
- var url = window.location.href;
- var loginUrls = [
- 'login_slogin.html',
- 'login_login.html'
- ];
- for (var i = 0; i < loginUrls.length; i++) {
- if (url.indexOf(loginUrls[i]) !== -1) return true;
- }
- return false;
- }
- /**
- * 自动获取当前学年
- * 优先从页面下拉框获取,失败则根据日期计算
- */
- function getCurrentAcademicYear() {
- // 尝试从页面获取
- var xnmSelect = document.getElementById('xnm');
- if (xnmSelect && xnmSelect.value) {
- var year = xnmSelect.value;
- console.log('JS: 从页面获取到学年: ' + year);
- return year;
- }
-
- // 根据当前日期计算学年
- var now = new Date();
- var year = now.getFullYear();
- var month = now.getMonth() + 1;
-
- // 9月及以后属于新学年
- if (month >= 9) {
- console.log('JS: 根据日期计算学年: ' + year);
- return year.toString();
- } else {
- console.log('JS: 根据日期计算学年: ' + (year - 1));
- return (year - 1).toString();
- }
- }
- /**
- * 自动获取当前学期
- * 优先从页面下拉框获取,失败则根据日期计算
- */
- function getCurrentSemesterIndex() {
- // 尝试从页面获取
- var xqmSelect = document.getElementById('xqm');
- if (xqmSelect && xqmSelect.value) {
- var xqm = xqmSelect.value;
- // xqm: 3=第一学期, 12=第二学期
- if (xqm === '3') {
- console.log('JS: 从页面获取到学期: 第一学期');
- return 0;
- } else if (xqm === '12') {
- console.log('JS: 从页面获取到学期: 第二学期');
- return 1;
- }
- }
-
- // 根据日期计算:9月-次年2月为第一学期,3月-7月为第二学期
- var month = new Date().getMonth() + 1;
- if (month >= 3 && month <= 7) {
- console.log('JS: 根据日期计算学期: 第二学期');
- return 1;
- } else {
- console.log('JS: 根据日期计算学期: 第一学期');
- return 0;
- }
- }
- function getSemesterCode(semesterIndex) {
- return semesterIndex === 0 ? '3' : '12';
- }
- function getSemesterName(semesterIndex) {
- return semesterIndex === 0 ? '第一学期' : '第二学期';
- }
- function validateDateInput(input) {
- console.log('JS: validateDateInput 被调用,输入: ' + input);
- if (/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/.test(input)) {
- console.log('JS: validateDateInput 验证通过');
- return false;
- } else {
- console.log('JS: validateDateInput 验证失败');
- return '请输入正确格式的开学日期(如2025-09-01)!';
- }
- }
- async function promptUserToStart() {
- console.log('JS: 流程开始:显示公告');
- return await window.AndroidBridgePromise.showAlert(
- '教务系统课表导入',
- '导入前请确保您已在浏览器中成功登录教务系统。',
- '好的,开始导入'
- );
- }
- async function confirmAcademicYear(year, semesterName) {
- console.log('JS: 显示学年学期确认弹窗');
- return await window.AndroidBridgePromise.showAlert(
- '确认学年学期',
- '检测到当前为 ' + year + '-' + (parseInt(year) + 1) + ' 学年' + semesterName + ',确认导入该学期课程吗?',
- '确认导入'
- );
- }
- async function getSemesterStartDate() {
- console.log('JS: 提示用户输入开学日期');
- return await window.AndroidBridgePromise.showPrompt(
- '选择开学日期',
- '请输入本学期开学日期(格式:YYYY-MM-DD,如2025-09-01):',
- '2025-09-01',
- 'validateDateInput'
- );
- }
- /**
- * 通过API请求和解析课程数据
- */
- async function fetchAndParseCourses(academicYear, semesterIndex) {
- AndroidBridge.showToast('正在请求课表数据...');
-
- var semesterCode = getSemesterCode(semesterIndex);
- var baseUrl = window.location.origin;
- var url = baseUrl + '/jwglxt/kbcx/xskbcx_cxXsgrkb.html?gnmkdm=N2151';
- var body = 'xnm=' + academicYear + '&xqm=' + semesterCode + '&kzlx=ck';
-
- console.log('JS: 发送请求到 ' + url + ', body: ' + body);
-
- try {
- var response = await fetch(url, {
- headers: {
- 'content-type': 'application/x-www-form-urlencoded;charset=UTF-8'
- },
- referer: baseUrl + '/jwglxt/kbcx/xskbcx_cxXskbcxIndex.html?gnmkdm=N2151',
- body: body,
- method: 'POST',
- credentials: 'include'
- });
-
- if (!response.ok) {
- throw new Error('网络请求失败。状态码: ' + response.status);
- }
-
- var jsonText = await response.text();
- var jsonData;
- try {
- jsonData = JSON.parse(jsonText);
- } catch (e) {
- console.error('JS: JSON解析失败,可能是会话过期:', e);
- AndroidBridge.showToast('数据返回格式错误,可能是您未成功登录或会话已过期。');
- return null;
- }
-
- var courses = parseJsonData(jsonData);
- if (courses.length === 0) {
- AndroidBridge.showToast('未找到任何课程数据,请检查所选学年学期是否正确。');
- return null;
- }
-
- console.log('JS: 课程数据解析成功,共找到 ' + courses.length + ' 门课程');
- return courses;
- } catch (error) {
- AndroidBridge.showToast('请求或解析失败: ' + error.message);
- console.error('JS: Fetch/Parse Error:', error);
- return null;
- }
- }
- async function saveCourses(parsedCourses) {
- AndroidBridge.showToast('正在保存 ' + parsedCourses.length + ' 门课程...');
- console.log('JS: 尝试保存 ' + parsedCourses.length + ' 门课程');
- try {
- await window.AndroidBridgePromise.saveImportedCourses(JSON.stringify(parsedCourses));
- console.log('JS: 课程保存成功');
- return true;
- } catch (error) {
- AndroidBridge.showToast('课程保存失败: ' + error.message);
- console.error('JS: Save Courses Error:', error);
- return false;
- }
- }
- async function saveConfig(startDate) {
- console.log('JS: 尝试保存课表配置,开学日期: ' + startDate);
- var config = {
- semesterStartDate: startDate,
- semesterTotalWeeks: 20,
- defaultClassDuration: 45,
- defaultBreakDuration: 10,
- firstDayOfWeek: 1
- };
- try {
- await window.AndroidBridgePromise.saveCourseConfig(JSON.stringify(config));
- AndroidBridge.showToast('课表配置更新成功!开学日期:' + startDate);
- console.log('JS: 配置保存成功');
- return true;
- } catch (error) {
- AndroidBridge.showToast('课表配置保存失败: ' + error.message);
- console.error('JS: Save Config Error:', error);
- return false;
- }
- }
- // 山东华宇工学院西区冬季作息时间
- var TimeSlots = [
- { number: 1, startTime: '08:10', endTime: '08:55' },
- { number: 2, startTime: '09:05', endTime: '09:50' },
- { number: 3, startTime: '10:15', endTime: '11:00' },
- { number: 4, startTime: '11:15', endTime: '12:00' },
- { number: 5, startTime: '14:40', endTime: '15:25' },
- { number: 6, startTime: '15:35', endTime: '16:20' },
- { number: 7, startTime: '16:30', endTime: '17:15' },
- { number: 8, startTime: '17:25', endTime: '18:10' },
- { number: 9, startTime: '19:10', endTime: '19:55' },
- { number: 10, startTime: '20:05', endTime: '20:50' }
- ];
- async function importPresetTimeSlots(timeSlots) {
- console.log('JS: 准备导入 ' + timeSlots.length + ' 个预设时间段');
- try {
- await window.AndroidBridgePromise.savePresetTimeSlots(JSON.stringify(timeSlots));
- AndroidBridge.showToast('预设时间段导入成功!');
- console.log('JS: 预设时间段导入成功');
- } catch (error) {
- AndroidBridge.showToast('导入时间段失败: ' + error.message);
- console.error('JS: Save Time Slots Error:', error);
- }
- }
- async function runImportFlow() {
- if (isLoginPage()) {
- AndroidBridge.showToast('导入失败:请先登录教务系统!');
- console.log('JS: 检测到当前在登录页面,终止导入');
- return;
- }
-
- var alertConfirmed = await promptUserToStart();
- if (!alertConfirmed) {
- AndroidBridge.showToast('用户取消了导入');
- console.log('JS: 用户取消了导入流程');
- return;
- }
-
- // 自动获取学年和学期
- var academicYear = getCurrentAcademicYear();
- var semesterIndex = getCurrentSemesterIndex();
- var semesterName = getSemesterName(semesterIndex);
-
- console.log('JS: 自动获取到学年: ' + academicYear + ', 学期: ' + semesterName);
-
- // 让用户确认
- var confirmResult = await confirmAcademicYear(academicYear, semesterName);
- if (!confirmResult) {
- AndroidBridge.showToast('导入已取消');
- console.log('JS: 用户取消确认学年学期');
- return;
- }
-
- var startDate = await getSemesterStartDate();
- if (startDate === null) {
- AndroidBridge.showToast('导入已取消');
- console.log('JS: 获取开学日期失败/取消,流程终止');
- return;
- }
- console.log('JS: 已选择开学日期: ' + startDate);
-
- var courses = await fetchAndParseCourses(academicYear, semesterIndex);
- if (courses === null) {
- console.log('JS: 课程获取或解析失败,流程终止');
- return;
- }
-
- var saveResult = await saveCourses(courses);
- if (!saveResult) {
- console.log('JS: 课程保存失败,流程终止');
- return;
- }
-
- var configResult = await saveConfig(startDate);
- if (!configResult) {
- console.log('JS: 配置保存失败,流程终止');
- return;
- }
-
- await importPresetTimeSlots(TimeSlots);
-
- AndroidBridge.showToast('课程导入成功,共导入 ' + courses.length + ' 门课程!');
- console.log('JS: 整个导入流程执行完毕并成功');
- AndroidBridge.notifyTaskCompletion();
- }
- runImportFlow();
|