-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathshu-web.user.js
458 lines (426 loc) · 19.8 KB
/
shu-web.user.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
// ==UserScript==
// @name 上海大学网站增强 - 刷课助手
// @namespace https://github.com/panghaibin/shu-web-js
// @version 3.5.2
// @description <选课系统>1.第二、三轮选课自助刷课,解放双手。【人人有课刷,抵制卖课狗】【支持多门课程同时刷】 2.选课学期自动选择 3.选课排名页面标红排名超过额定人数的课程 4.学分完成情况页面,原始成绩换算绩点,选课学期可标红 5.所有存在显示课程号的页面,支持点击课程号查看课程介绍,右键直接复制课程号 <教务管理>1.教学评估页面可一键赋值,支持全部赋值和单行赋值 2.成绩查询页面在成绩未发布时自动刷新 3.移除主页企业微X广告
// @author panghaibin
// @match *://xk.autoisp.shu.edu.cn/*
// @match *://cj.shu.edu.cn/*
// @grant none
// @license MIT
// @supportURL https://github.com/panghaibin/shu-web-js/issues
// ==/UserScript==
(function () {
'use strict';
//--------刷课配置 开始--------
// 是否开启刷课 (true: 开启 false: 关闭)
let START_SELECT = false;
// 课程设置,可设置多个
let COURSE_SETTING = [
// 格式: ['课程号', '教师号'],
// 以下两个为示例 记得修改或删除,也可增加更多
['0085X078', '1091'],
['0085X078', '1331'],
];
// 刷课间隔,默认 8000 ,单位毫秒 一般不需要修改
let SELECT_DELAY = 8000
//--------刷课配置 结束--------
if (location.host === 'xk.autoisp.shu.edu.cn') {
if (location.pathname === '/CourseSelectionStudent/PlanQuery') {
plan_query_page();
} else if (location.pathname === '/StudentQuery/QueryEnrollRank') {
rclick_copy_course_id();
red_rank();
} else if (location.pathname === '/CourseSelectionStudent/FuzzyQuery' && START_SELECT) {
select_course_helper();
} else if (location.pathname === '/Home/TermIndex' && location.search !== '?auto_select=0') {
auto_select_term();
} else if (location.pathname === '/StudentQuery/QueryCourse'
|| location.pathname === '/StudentQuery/QueryCourseTable'
|| location.pathname === '/StudentQuery/QueryDeleteCourse'
) {
rclick_copy_course_id();
}
if (location.pathname !== '/Home/TermIndex') {
manual_select_term();
add_xk_footer();
}
} else if (location.host === 'cj.shu.edu.cn') {
if (location.pathname === '/StudentPortal/Evaluate') {
evaluate_helper();
} else if (location.pathname === '/Home/StudentIndex') {
remove_cj_ad();
} else if (location.pathname === '/StudentPortal/ScoreQuery') {
auto_fresh_score();
}
}
function score_conversion(item) {
let score_num = item.innerText * 1;
let score_raw = item.innerText;
if (score_raw.length > 0) {
if (score_num >= 90 && score_num <= 100 || score_raw === "A") {
item.innerText = score_raw + ' / 4.0';
} else if (score_num >= 85 && score_num <= 89.9 || score_raw === "A-") {
item.innerText = score_raw + ' / 3.7';
} else if (score_num >= 82 && score_num <= 84.9 || score_raw === "B+") {
item.innerText = score_raw + ' / 3.3';
} else if (score_num >= 78 && score_num <= 81.9 || score_raw === "B") {
item.innerText = score_raw + ' / 3.0';
} else if (score_num >= 75 && score_num <= 77.9 || score_raw === "B-") {
item.innerText = score_raw + ' / 2.7';
} else if (score_num >= 72 && score_num <= 74.9 || score_raw === "C+") {
item.innerText = score_raw + ' / 2.3';
} else if (score_num >= 68 && score_num <= 71.9 || score_raw === "C") {
item.innerText = score_raw + ' / 2.0';
} else if (score_num >= 66 && score_num <= 67.9 || score_raw === "C-") {
item.innerText = score_raw + ' / 1.7';
} else if (score_num >= 64 && score_num <= 65.9 || score_raw === "D") {
item.innerText = score_raw + ' / 1.5';
} else if (score_num >= 60 && score_num <= 63.9 || score_raw === "D-") {
item.innerText = score_raw + ' / 1.0';
} else if ((score_num >= 0 && score_num <= 59.9 || score_raw === "F")) {
item.innerText = score_raw + ' / 0.0';
} else if (score_raw === "P" || score_raw === "L") {
item.innerText = score_raw + ' / 不计';
}
// 标红压线绩点 暂时不使用
// if (score_num === 89 || score_num === 84 || score_num === 81 || score_num === 77 || score_num === 74 ||
// score_num === 71 || score_num === 67 || score_num === 65 || score_num === 63 || score_num === 59) {
// item.style.color = 'red';
// }
}
}
function red_rank() {
let elements;
elements = document.getElementsByName('rowclass');
for (let i = 0; i < elements.length; ++i) {
let row = elements[i];
let room = row.children[4].innerText * 1;
let _rank = row.children[6].innerText.split('-');
let rank = _rank[_rank.length - 1] * 1;
if (rank > room) {
for (let j = 0; j < row.children.length; ++j) {
elements[i].children[j].style.color = 'red';
elements[i].children[j].style.fontWeight = 'bold';
}
}
}
}
function select_course_helper() {
let i = 0;
let select_id = setInterval(function () {
const index = i % COURSE_SETTING.length;
const course = COURSE_SETTING[index]
const course_id = course[0];
const teacher_id = course[1];
document.getElementsByName('CID')[0].defaultValue = course_id;
document.getElementsByName('TeachNo')[0].defaultValue = teacher_id;
document.getElementById('QueryAction').click();
setTimeout(function () {
let tbllist = document.getElementsByClassName('tbllist');
let room = tbllist[0].children[0].children[1].children[9].innerText * 1;
let num = tbllist[0].children[0].children[1].children[10].innerText * 1;
console.log('第' + ++i + '次 课程号' + course_id + ' 教师号' + teacher_id + ' 容量' + room + ' 人数' + num);
if (room > num) {
tbllist[0].children[0].children[1].children[0].children[0].checked = true;
document.getElementById('CourseCheckAction').click();
let across_campus = document.getElementById('NotCollegeAction');
if (across_campus != null) {
setTimeout(function () {
across_campus.click();
}, 1000);
}
tbllist = document.getElementsByClassName('tbllist');
let callback_msg = tbllist[1].children[0].children[1].children[5].innerText
if (callback_msg.includes('成功')) {
COURSE_SETTING.splice(index, 1);
if (COURSE_SETTING.length === 0) {
clearInterval(select_id);
} else {
CloseDialog('divOperationResult');
}
} else {
// 关闭选课失败的窗口
CloseDialog('divOperationResult');
}
console.log(callback_msg);
}
}, 1000);
}, SELECT_DELAY);
}
function evaluate_helper() {
let tbllist = document.getElementsByClassName('tbllist');
let th = document.createElement('TH');
th.innerText = '一键评估';
let heading = tbllist[0].children[0].children[0];
heading.insertBefore(th, heading.children[4]);
let evaluate_list = ['结果', '非常大', '比较大', '一般', '很少'];
let course_count = tbllist[0].children[0].childElementCount - 2;
for (let i = 1; i <= course_count; ++i) {
let select = document.createElement('SELECT');
select.style.backgroundColor = '#ffc';
for (let j = 0; j < evaluate_list.length; j++) {
let option = document.createElement('OPTION');
option.innerText = evaluate_list[j];
option.value = j;
if (j === 0) {
option.innerText = '单行' + option.innerText;
option.selected = true;
}
select.appendChild(option);
}
select._params = {'row': i - 1};
select.addEventListener('change', function () {
let row = event.target._params['row']
for (let j = 0; j < 4; ++j) {
let evaluate_name = 'classlist[' + row + '].ItemValue[' + j + ']';
let raw_select = document.getElementsByName(evaluate_name);
raw_select[0].children[this.value].selected = true;
}
}, false);
let td = document.createElement('TD');
td.appendChild(select);
let cource = tbllist[0].children[0].children[i];
cource.insertBefore(td, cource.children[4]);
}
let all_select = document.createElement('SELECT');
all_select.style.backgroundColor = '#ffc';
all_select.style.marginRight = '15px';
for (let i = 0; i < evaluate_list.length; i++) {
let option = document.createElement('OPTION');
option.innerText = evaluate_list[i];
option.value = i;
if (i === 0) {
option.innerText = '全部' + option.innerText;
option.selected = true;
}
all_select.appendChild(option);
}
all_select.addEventListener('change', function () {
let selects = document.getElementsByTagName('SELECT');
for (let i = 0; i < selects.length; ++i) {
selects[i].children[this.value].selected = true;
}
}, false);
let row = tbllist[0].children[0].children;
let last_row = row[row.length - 1].children[0].children[0];
let save_btn = last_row.children[0];
last_row.insertBefore(all_select, save_btn);
}
function remove_cj_ad() {
document.getElementsByClassName('div_master_content')[0].remove();
}
function auto_select_term() {
let term_list = document.getElementsByName('rowterm');
document.getElementById('termId').value = term_list[term_list.length - 1].getAttribute('value');
document.getElementsByTagName('button')[0].click();
}
function manual_select_term() {
let menu = document.querySelector('.term-menu');
if (menu !== null) {
let a_tag = menu.getElementsByTagName('a')[0];
a_tag.href = a_tag.href + '?auto_select=0';
}
}
function add_xk_footer() {
setInterval(() => {
let footer = document.getElementsByClassName('main-footer')[0];
if (typeof (footer) !== "undefined") {
let footer_div = footer.children[1];
if (!footer_div.innerHTML.includes('刷课助手')) {
let skzs = document.createElement('A');
skzs.innerText = '刷课助手已加载';
skzs.href = 'https://greasyfork.org/zh-CN/scripts/434613';
skzs.target = '_blank';
footer_div.innerHTML = footer_div.innerHTML + ' - ' + skzs.outerHTML;
}
}
}, 0)
}
function get_current_grade_term() {
let term_name = document.getElementsByClassName('dropdownterm')[0].children[0].children[1].innerText;
let term_year = /(\d{2})学年/.exec(term_name)[1] * 1;
let term_type = /(.)季学期/.exec(term_name)[1];
let id_num = document.getElementsByClassName('nav-function-text')[0].innerText;
let enroll_year = /(\d{2})\d{6}/.exec(id_num)[1] * 1;
let term_list = {'秋': 1, '冬': 2, '春': 3, '夏': 4};
let term_num = term_list[term_type];
let grade_num = term_year - enroll_year;
return {'class': 'gt-' + grade_num + term_num, 'grade': grade_num, 'term': term_num};
}
function onchange_grade_term_select() {
let all_gt = document.getElementsByClassName('gt');
for (let i = 0; i < all_gt.length; i++) {
all_gt[i].style.color = '';
}
let grade_choice = document.getElementsByClassName('grade-select')[0].value;
let term_choice = document.getElementsByClassName('term-select')[0].value;
let choice_gt = document.getElementsByClassName('gt-' + grade_choice + term_choice);
for (let i = 0; i < choice_gt.length; i++) {
choice_gt[i].style.color = 'red';
}
}
function plan_query_page() {
let grade_list = {'一': 1, '二': 2, '三': 3, '四': 4, '五': 5};
let term_list = {'秋': 1, '冬': 2, '春': 3, '夏': 4};
let td_list = document.getElementsByTagName('TD');
for (let i = 0; i < td_list.length; i++) {
if (td_list[i].innerText.includes('学期')) {
td_list[i].innerHTML = td_list[i].innerHTML.replaceAll(/(.)年级(.)季学期/g,
function ($0, $1, $2) {
let span = document.createElement('SPAN');
span.className = 'gt gt-' + grade_list[$1] + '0 gt-' + grade_list[$1] + term_list[$2];
span.innerText = $0;
return span.outerHTML;
});
} else if (is_cource_id_td(td_list[i])) {
edit_cource_id_td(td_list[i]);
} else if (typeof (td_list[i].attributes.name) !== "undefined"
&& ['tdscorecnotpass', 'tdscore', 'tdscorecpass'].includes(td_list[i].attributes.name.value)) {
score_conversion(td_list[i]);
}
}
let reverse_grade_list = {1: '一', 2: '二', 3: '三', 4: '四', 5: '五'};
let reverse_term_list = {1: '秋季', 2: '冬季', 3: '春季', 4: '夏季', 0: '全部'};
let current_grade_term = get_current_grade_term();
let grade_select = document.createElement('SELECT');
grade_select.className = 'grade-select';
grade_select.style.backgroundColor = '#ffc';
grade_select.addEventListener('change', onchange_grade_term_select);
let grade_val = current_grade_term['grade'];
for (let i = 1; i <= 5; i++) {
let option = document.createElement('OPTION');
option.innerText = reverse_grade_list[i] + '年级';
option.value = i;
if (grade_val === i) {
option.selected = true;
}
grade_select.appendChild(option);
}
let term_select = document.createElement('SELECT');
term_select.className = 'term-select';
term_select.style.backgroundColor = '#ffc';
term_select.addEventListener('change', onchange_grade_term_select);
let term_val = current_grade_term['term'];
for (let i = 0; i <= 4; i++) {
let option = document.createElement('OPTION');
option.innerText = reverse_term_list[i] + '学期';
option.value = i;
if (term_val === i) {
option.selected = true;
}
term_select.appendChild(option);
}
let th_list = document.getElementsByTagName('TH');
for (let i = 0; i < th_list.length; i++) {
if (th_list[i].innerText.includes('教学计划')) {
th_list[i].appendChild(grade_select);
th_list[i].appendChild(term_select);
break;
}
}
let gt_class = document.getElementsByClassName(current_grade_term['class']);
for (let i = 0; i < gt_class.length; i++) {
gt_class[i].style.color = 'red';
}
}
function fresh_score(interval_id) {
let score_table = document.getElementById('divList');
if (score_table.innerText.includes('学号') && !score_table.innerText.includes('未提交')) {
if (interval_id !== null) {
let title = '成绩已发布';
blink_title(title);
clearInterval(interval_id);
}
return false;
} else if (score_table.innerText.includes('评估')) {
let title = '成绩已发布,教学评估完成后可查看';
blink_title(title);
clearInterval(interval_id);
return false;
} else {
score_table.innerHTML = score_table.innerHTML + '<br>8秒后自动刷新';
return true;
}
}
function auto_fresh_score() {
let interval_id = null;
if (fresh_score(interval_id)) {
let i = 0;
interval_id = setInterval(function () {
document.title = '已刷新' + ++i + '次成绩';
document.getElementsByTagName('INPUT')[0].click();
setTimeout(fresh_score, 2000, interval_id);
}, 8000);
}
}
function rclick_copy_course_id() {
setInterval(function () {
let td_list = document.getElementsByTagName('TD');
for (let i = 0; i < td_list.length; i++) {
if (is_cource_id_td(td_list[i])) {
edit_cource_id_td(td_list[i]);
}
}
}, 500);
}
function is_cource_id_td(item) {
return item.innerText.length === 8 && /\d.{6}\d/.test(item.innerText);
}
function edit_cource_id_td(item) {
let course_id = item.innerText;
item.className = 'course-id';
item.style.cursor = 'pointer';
item.title = '点击查看课程简介,右键复制课程号';
item.oncontextmenu = function (e) {
e.preventDefault();
copy_to_clipboard(course_id)
.then(() => toast_msg(item, '已复制'))
.catch(() => toast_msg(item, '复制失败'));
}
item.onclick = function () {
window.open("../DataQuery/QueryCourseIntro?courseNo=" + course_id);
}
}
function copy_to_clipboard(text) {
// From https://stackoverflow.com/a/65996386
if (navigator.clipboard && window.isSecureContext) {
return navigator.clipboard.writeText(text);
} else {
let textArea = document.createElement("textarea");
textArea.value = text;
textArea.style.position = "fixed";
textArea.style.left = "-999999px";
textArea.style.top = "-999999px";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
return new Promise((res, rej) => {
document.execCommand('copy') ? res() : rej();
textArea.remove();
});
}
}
function toast_msg(item, msg) {
let toast = document.createElement('span');
toast.className = 'toast';
toast.style.fontSize = '0.8em';
toast.innerText = '\n' + msg;
item.appendChild(toast);
setTimeout(function () {
toast.remove();
}, 500);
}
function blink_title(title_text, times = 0) {
let space = ('—').repeat(title_text.length);
if (times === 0) {
document.title = space;
} else if (times === 1) {
document.title = title_text;
}
times = (times + 1) % 2;
setTimeout(function () {
blink_title(title_text, times);
}, 800);
}
})();