| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- // 山东轻工职业学院(sdlivc.cn) 拾光课程表适配脚本
- // 数据来源:教务系统 /jedu/edu/core/eduScheduleInfo/getScheduleNew.do
- (function () {
- const ROOT_PATH = window.__rootPath || '/jedu';
- const WEEK_MAP = {
- mon: 1,
- tue: 2,
- wed: 3,
- thu: 4,
- fri: 5,
- sat: 6,
- sun: 7
- };
- function showToast(message) {
- if (window.AndroidBridge && typeof window.AndroidBridge.showToast === 'function') {
- window.AndroidBridge.showToast(message);
- } else {
- console.log('[Toast]', message);
- }
- }
- function getStudentId() {
- if (typeof window.stuId === 'string' && window.stuId.trim()) {
- return window.stuId.trim();
- }
- const html = document.body ? document.body.innerHTML : '';
- const match = html.match(/var\s+stuId\s*=\s*["']([^"']+)["']/);
- return match ? match[1] : '';
- }
- function getSelectedSemesterId() {
- if (typeof mini !== 'undefined' && typeof mini.get === 'function') {
- const picker = mini.get('semId');
- if (picker && typeof picker.getValue === 'function') {
- return picker.getValue() || '';
- }
- }
- const input = document.querySelector('input[name="semId"], #semId');
- return input ? input.value || '' : '';
- }
- function toDayNumber(week) {
- return WEEK_MAP[String(week || '').toLowerCase()] || null;
- }
- function expandWeekRange(start, end, parity) {
- const weeks = [];
- const from = Math.min(start, end);
- const to = Math.max(start, end);
- for (let week = from; week <= to; week += 1) {
- if (parity === 'odd' && week % 2 === 0) continue;
- if (parity === 'even' && week % 2 !== 0) continue;
- weeks.push(week);
- }
- return weeks;
- }
- function parseWeeks(weekList) {
- if (!weekList) return [];
- const weeks = new Set();
- const normalized = String(weekList)
- .replace(/\s+/g, '')
- .replace(/,/g, ',')
- .replace(/(/g, '(')
- .replace(/)/g, ')')
- .replace(/第/g, '')
- .replace(/周/g, '');
- for (const rawPart of normalized.split(',')) {
- if (!rawPart) continue;
- const parity = rawPart.includes('单') ? 'odd' : rawPart.includes('双') ? 'even' : null;
- const numberPart = rawPart.replace(/\([^)]*\)/g, '');
- const rangeMatch = numberPart.match(/^(\d+)-(\d+)$/);
- const singleMatch = numberPart.match(/^(\d+)$/);
- if (rangeMatch) {
- expandWeekRange(Number(rangeMatch[1]), Number(rangeMatch[2]), parity)
- .forEach(week => weeks.add(week));
- } else if (singleMatch) {
- const week = Number(singleMatch[1]);
- if (parity === 'odd' && week % 2 === 0) continue;
- if (parity === 'even' && week % 2 !== 0) continue;
- weeks.add(week);
- }
- }
- return Array.from(weeks).sort((a, b) => a - b);
- }
- function cleanPlaceName(item) {
- const place = item && item.eduPlace ? item.eduPlace : {};
- return place.placeName || place.nameIncludeNum || '';
- }
- function convertScheduleItem(item) {
- if (!item || item.stopCourse !== 'NO') return null;
- const lesson = item.eduLesson || {};
- const day = toDayNumber(item.week);
- const weeks = parseWeeks(item.weekList);
- const startSection = Number(lesson.startLesson);
- const endSection = Number(lesson.endLesson);
- if (!item.courseName || !day || !startSection || !endSection || weeks.length === 0) {
- return null;
- }
- return {
- name: item.courseName,
- teacher: item.teacherName || '',
- position: cleanPlaceName(item),
- day,
- startSection,
- endSection,
- weeks,
- isCustomTime: false
- };
- }
- function mergeCourses(courses) {
- const courseMap = new Map();
- courses.forEach(course => {
- const key = [
- course.name,
- course.teacher,
- course.position,
- course.day,
- course.startSection,
- course.endSection
- ].join('|');
- const existing = courseMap.get(key);
- if (existing) {
- existing.weeks = Array.from(new Set(existing.weeks.concat(course.weeks))).sort((a, b) => a - b);
- } else {
- courseMap.set(key, Object.assign({}, course, {
- weeks: Array.from(new Set(course.weeks)).sort((a, b) => a - b)
- }));
- }
- });
- return Array.from(courseMap.values());
- }
- function getMaxWeek(courses) {
- const weeks = courses.flatMap(course => Array.isArray(course.weeks) ? course.weeks : []);
- return weeks.length > 0 ? Math.max.apply(null, weeks) : 20;
- }
- async function fetchSchedule() {
- const stuId = getStudentId();
- if (!stuId) {
- throw new Error('未找到学生 ID,请先通过学生信息系统进入“学期课表”页面。');
- }
- const params = new URLSearchParams({
- semId: getSelectedSemesterId(),
- stuId,
- checkType: 'student'
- });
- const response = await fetch(ROOT_PATH + '/edu/core/eduScheduleInfo/getScheduleNew.do', {
- method: 'POST',
- credentials: 'same-origin',
- headers: {
- 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
- 'X-Requested-With': 'XMLHttpRequest'
- },
- body: params.toString()
- });
- if (!response.ok) {
- throw new Error('课表接口请求失败:HTTP ' + response.status);
- }
- const json = await response.json();
- if (!json || json.success !== true) {
- throw new Error((json && json.message) || '课表接口返回失败。');
- }
- return json.data && Array.isArray(json.data.schedule) ? json.data.schedule : [];
- }
- async function saveImportedData(courses) {
- const courseResult = await window.AndroidBridgePromise.saveImportedCourses(JSON.stringify(courses));
- if (courseResult !== true) {
- throw new Error('课程保存失败:' + courseResult);
- }
- if (typeof window.AndroidBridgePromise.saveCourseConfig === 'function') {
- const configResult = await window.AndroidBridgePromise.saveCourseConfig(JSON.stringify({
- semesterTotalWeeks: getMaxWeek(courses),
- defaultClassDuration: 45,
- defaultBreakDuration: 10,
- firstDayOfWeek: 1
- }));
- if (configResult !== true) {
- throw new Error('课表配置保存失败:' + configResult);
- }
- }
- }
- async function promptUserToStart() {
- if (!window.AndroidBridgePromise || typeof window.AndroidBridgePromise.showAlert !== 'function') {
- return true;
- }
- return await window.AndroidBridgePromise.showAlert(
- '山东轻工职业学院课表导入',
- '请确认已登录并进入“学期课表”页面。脚本将读取当前学期课表并导入拾光课程表。',
- '开始导入'
- );
- }
- async function runImportFlow() {
- try {
- const confirmed = await promptUserToStart();
- if (!confirmed) return;
- showToast('正在读取学期课表...');
- const rawSchedule = await fetchSchedule();
- const courses = mergeCourses(rawSchedule.map(convertScheduleItem).filter(Boolean));
- if (courses.length === 0) {
- showToast('未解析到可导入课程');
- return;
- }
- await saveImportedData(courses);
- showToast('成功导入 ' + courses.length + ' 条课程');
- window.AndroidBridge.notifyTaskCompletion();
- } catch (error) {
- console.error('山东轻工职业学院课表导入失败', error);
- showToast('课表导入失败:' + error.message);
- }
- }
- window.__sdlivcImporter = {
- parseWeeks,
- toDayNumber,
- convertScheduleItem,
- mergeCourses,
- getMaxWeek,
- saveImportedData
- };
- if (window.__SDLIVC_AUTO_RUN__ !== false) {
- runImportFlow();
- }
- }());
|