Warning: fopen(/www/sites/update.greasyfork.icu/index/store/temp/bdff4bff2b0c78b33d82ce3b8ecec67b.js): failed to open stream: No space left on device in /www/sites/update.greasyfork.icu/index/scriptControl.php on line 65
// ==UserScript==
// @name 杭师大新版教务系统导出课表
// @namespace http://tampermonkey.net/
// @version 0.1
// @description 将杭师大新版教务系统中的课表导出为 ICS 格式方便导入日历中。
// @author Juskinbo
// @supportURL https://github.com/Juskinbo/HZNU2ICS
// @include *://jwxt.hznu.edu.cn/*
// @license MIT
// @downloadURL https://update.greasyfork.icu/scripts/469768/%E6%9D%AD%E5%B8%88%E5%A4%A7%E6%96%B0%E7%89%88%E6%95%99%E5%8A%A1%E7%B3%BB%E7%BB%9F%E5%AF%BC%E5%87%BA%E8%AF%BE%E8%A1%A8.user.js
// @updateURL https://update.greasyfork.icu/scripts/469768/%E6%9D%AD%E5%B8%88%E5%A4%A7%E6%96%B0%E7%89%88%E6%95%99%E5%8A%A1%E7%B3%BB%E7%BB%9F%E5%AF%BC%E5%87%BA%E8%AF%BE%E8%A1%A8.meta.js
// ==/UserScript==
// 网站后缀
var ClassScheduleURL = "kbcx/xskbcx_cxXskbcxIndex.html"; // 学生课表查询页面
var ExamScheduleURL = "kwgl/kscx_cxXsksxxIndex.html"; // 考试信息查询页面
var StudentEvalutionURL = "xspjgl/xspj_cxXspjIndex.html"; // 学生评教页面
var setTimeout_ = 4000; // 设置脚本实际运行的开始时间,网络不好建议时间稍长,1000等于1s
(function () {
"use strict";
unsafeWindow.addEventListener("load", main); // 等待页面加载完成后运行
})();
function main() {
var windowURL = window.location.href; // 获取当前页面的URL
if (windowURL.indexOf(ClassScheduleURL) != -1) {
// 如果当前页面的URL中包含课表查询页面的URL
ClassSchedule2ICS();
} else if (windowURL.indexOf(ExamScheduleURL) != -1) {
// 如果当前页面的URL中包含考试信息查询页面的URL
ExamSchedule2ICS();
} else if (windowURL.indexOf(StudentEvalutionURL) != -1) {
// StudentEvalution();
// unsafeWindow.addEventListener("load", StudentEvalution);
document.getElementById("btn_yd").onclick = function () {
window.setTimeout(StudentEvalution, setTimeout_);
};
}
}
// 导出考试信息
function ExamSchedule2ICS() {
console.log("ExamSchedule2ICS");
pageLoaded();
function pageLoaded() {
let div = document.getElementById("but_ancd");
let btn = document.createElement("button");
btn.className = "btn btn-default btn-dc";
btn.id = "exportbtn";
btn.innerText = "导出 ICS 文件";
div.appendChild(btn);
btn.onclick = function () {
generateCalendar();
alert("已自动下载 ICS 文件");
};
}
function generateCalendar() {
let table = document.getElementById("tabGrid");
// 课程
// 考试时间
// 考试地点
// 考试校区
// 考试座号
class EXAM {
constructor(e) {
if (e) {
this.course = e.course; // 课程名
this.timeS = e.timeS; // 考试开始时间
this.timeE = e.timeE; // 考试结束时间
this.location = e.location; // 考试地点组成: 考试地点、考试校区、座位号
}
}
}
let exams = new Array();
table.querySelectorAll("tr").forEach((tr) => {
let exam = new EXAM();
tr.querySelectorAll("td").forEach((td) => {
let attr = td.getAttribute("aria-describedby");
if (attr == "tabGrid_kcmc") {
// 课程
exam.course = td.innerText;
} else if (attr == "tabGrid_kssj") {
// 考试时间
let time = td.innerText;
let date =
"" +
time[0] +
time[1] +
time[2] +
time[3] +
time[5] +
time[6] +
time[8] +
time[9] +
"T";
exam.timeS = date + time[11] + time[12] + time[14] + time[15] + "00";
exam.timeE = date + time[17] + time[18] + time[20] + time[21] + "00";
} else if (attr == "tabGrid_cdmc") {
// 考试地点
exam.location = td.innerText;
} else if (attr == "tabGrid_cdxqmc") {
// 考试校区
exam.location = td.innerText + exam.location;
} else if (attr == "tabGrid_zwh") {
// 考试座号
exam.location += " 座位号" + td.innerText;
}
});
exams.push(exam);
});
let ics = new ICS();
exams.forEach((ex) => {
let e = new ICSEvent(
"" + ex.timeS,
"" + ex.timeE,
"" + ex.course + " " + ex.location
);
ics.pushEvent(e);
});
ics.pushCalendarEnd();
ics.exportIcs();
}
}
var CRLF = "\n";
var SPACE = " ";
class ICS {
Calendar; // 日历参数
ics; // ics格式的日历
res; // 最后格式化的结果
constructor() {
(function (Calendar) {
Calendar.PRODID = "-//Juskinbo//ICalendar Exporter v1.0//CN";
Calendar.VERSION = "2.0";
Calendar.CALSCALE = "GREGORIAN"; // 历法,默认是公历
Calendar.TIMEZONE = "Asia/Shanghai"; // 时区,默认是上海
Calendar.ISVALARM = true; // 提醒,默认是开启
Calendar.VALARM = "-P0DT0H30M0S"; // 提醒,默认半小时
Calendar.WKST = "SU"; // 一周开始,默认是周日
})(this.Calendar || (this.Calendar = {}));
this.ics = new Array();
this.ics.push("BEGIN:VCALENDAR");
this.ics.push("VERSION:" + this.Calendar.VERSION);
this.ics.push("PRODID:" + this.Calendar.PRODID);
this.ics.push("CALSCALE:" + this.Calendar.CALSCALE);
}
// 添加事件
pushEvent(e) {
this.ics.push("BEGIN:VEVENT");
this.ics.push(e.getDTSTART());
this.ics.push(e.getDTEND());
if (e.isrrule == true) this.ics.push(e.getRRULE());
this.ics.push(e.getSUMMARY());
if (this.Calendar.ISVALARM == true) this.pushAlarm();
this.ics.push("END:VEVENT");
this.ics.push(CRLF);
}
// 添加提醒
pushAlarm() {
this.ics.push("BEGIN:VALARM");
this.ics.push("ACTION:DISPLAY");
this.ics.push("DESCRIPTION:This is an event reminder");
this.ics.push("TRIGGER:" + this.Calendar.VALARM);
this.ics.push("END:VALARM");
}
// 结束日历
pushCalendarEnd() {
this.ics.push("END:VCALENDAR");
}
// 格式化ics文件
getFixedIcs() {
this.res = "";
this.ics.forEach((line) => {
if (line.length > 60) {
let len = line.length;
let index = 0;
while (len > 0) {
for (let i = 0; i < index; ++i) {
this.res += SPACE;
}
this.res += line.slice(0, 60) + CRLF;
line = line.slice(61);
len -= 60;
++index;
}
line = line.slice(0, 60);
}
this.res += line + CRLF;
});
return this.res;
}
// 导出ics文件并下载
exportIcs() {
this.getFixedIcs();
// 使用a标签模拟下载,blob实现流文件的下载链接转化
let link = window.URL.createObjectURL(
new Blob([this.res], {
type: "text/x-vCalendar",
})
);
let a = document.createElement("a");
a.setAttribute("href", link);
a.setAttribute("download", "courses.ics");
a.click();
}
}
class ICSEvent {
constructor(DTSTART, DTEND, SUMMARY) {
this.DTSTART = DTSTART;
this.DTEND = DTEND;
this.SUMMARY = SUMMARY;
}
isrrule = false;
RRULE;
setRRULE(FREQ, WKST, COUNT, INTERVAL, BYDAY) {
this.isrrule = true;
this.RRULE =
"RRULE:FREQ=" +
FREQ +
";WKST=" +
WKST +
";COUNT=" +
COUNT +
";INTERVAL=" +
INTERVAL +
";BYDAY=" +
BYDAY;
}
getRRULE() {
return "" + this.RRULE;
}
getDTSTART() {
return "DTSTART:" + this.DTSTART;
}
getDTEND() {
return "DTEND:" + this.DTEND;
}
getSUMMARY() {
return "SUMMARY:" + this.SUMMARY;
}
}