Skip to content

Commit ec99fe0

Browse files
committed
feat(clients): 添加一般课表获取
1 parent 03eb9b9 commit ec99fe0

File tree

5 files changed

+335
-3
lines changed

5 files changed

+335
-3
lines changed

auth/cas.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,24 @@ export default class CASAuth {
344344
}
345345
}
346346

347+
async loginHUBM() {
348+
const url = 'http://hub.m.hust.edu.cn/hub_weix';
349+
const isLogin = await this.checkLoginStatus();
350+
351+
if (!isLogin) {
352+
return false;
353+
}
354+
355+
try {
356+
let response = await this.axios.get(url);
357+
response = await followRedirect(response, this.axios);
358+
359+
return response.status === 200;
360+
} catch (e) {
361+
return false;
362+
}
363+
}
364+
347365
async loginONE() {
348366
const url = 'https://one.hust.edu.cn/dcp/';
349367
const isLogin = await this.checkLoginStatus();

clients/course-client.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import axios from 'axios';
33
import { useCookie } from '@/utils/use-cookie';
44
import type HUST from '..';
55
import { getPhysicsCourseGrades, getPhysicsCourseSchedule as getPhysicsCourseSchedule } from './course/physics';
6+
import { getNormalCourseSchedule } from './course/course';
67

78
export default class CourseClient {
89
protected readonly axios: AxiosInstance;
@@ -33,4 +34,10 @@ export default class CourseClient {
3334
getPhysicsCourseGrades(this.axios),
3435
);
3536
}
36-
}
37+
38+
async getNormalCourseSchedule(semesterId: string) {
39+
return await this.hust.handleRequest(() =>
40+
getNormalCourseSchedule(this.axios, semesterId),
41+
);
42+
}
43+
}

clients/course/course.ts

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
import type {
2+
NormalCourseSchedule,
3+
NormalCourseScheduleResponse,
4+
} from '@/types/clients/course/course';
5+
import type { AxiosInstance } from 'axios';
6+
import type { Dayjs } from 'dayjs';
7+
import dayjs from 'dayjs';
8+
9+
function getStartTimeFromLesson(lesson: number, date: Dayjs): Dayjs {
10+
const mayDay = date
11+
.clone()
12+
.set('month', 5)
13+
.set('day', 1)
14+
.set('hour', 0)
15+
.set('minute', 0)
16+
.set('second', 0);
17+
const nationalDay = date
18+
.clone()
19+
.set('month', 10)
20+
.set('day', 1)
21+
.set('hour', 0)
22+
.set('minute', 0)
23+
.set('second', 0);
24+
25+
if (date >= mayDay && date < nationalDay) {
26+
switch (lesson) {
27+
case 1:
28+
return date.hour(8).minute(0);
29+
case 2:
30+
return date.hour(8).minute(55);
31+
case 3:
32+
return date.hour(10).minute(10);
33+
case 4:
34+
return date.hour(11).minute(5);
35+
case 5:
36+
return date.hour(14).minute(0);
37+
case 6:
38+
return date.hour(14).minute(50);
39+
case 7:
40+
return date.hour(15).minute(55);
41+
case 8:
42+
return date.hour(16).minute(45);
43+
case 9:
44+
return date.hour(18).minute(30);
45+
case 10:
46+
return date.hour(19).minute(20);
47+
case 11:
48+
return date.hour(20).minute(15);
49+
case 12:
50+
return date.hour(21).minute(5);
51+
default:
52+
throw new Error(`Invalid lesson number: ${lesson}`);
53+
}
54+
} else {
55+
switch (lesson) {
56+
case 1:
57+
return date.hour(8).minute(0);
58+
case 2:
59+
return date.hour(8).minute(55);
60+
case 3:
61+
return date.hour(10).minute(10);
62+
case 4:
63+
return date.hour(11).minute(5);
64+
case 5:
65+
return date.hour(14).minute(30);
66+
case 6:
67+
return date.hour(15).minute(20);
68+
case 7:
69+
return date.hour(16).minute(25);
70+
case 8:
71+
return date.hour(17).minute(15);
72+
case 9:
73+
return date.hour(19).minute(0);
74+
case 10:
75+
return date.hour(19).minute(50);
76+
case 11:
77+
return date.hour(20).minute(45);
78+
case 12:
79+
return date.hour(21).minute(35);
80+
default:
81+
throw new Error(`Invalid lesson number: ${lesson}`);
82+
}
83+
}
84+
}
85+
86+
function getEndTimeFromLesson(lesson: number, date: Dayjs): Dayjs {
87+
const startTime = getStartTimeFromLesson(lesson, date);
88+
return startTime.add(45, 'minute');
89+
}
90+
91+
export async function getNormalCourseSchedule(
92+
axios: AxiosInstance,
93+
semesterId: string,
94+
): Promise<NormalCourseSchedule[]> {
95+
const url = `https://hubs.hust.edu.cn/schedule/getStudentScheduleByXqh?XQH=${semesterId}`;
96+
97+
try {
98+
const response = await axios.get(url);
99+
if (response.status !== 200) {
100+
throw new Error(
101+
`Error fetching course schedule for semester ${semesterId}.`,
102+
);
103+
}
104+
const data: NormalCourseScheduleResponse = response.data;
105+
106+
const results: NormalCourseSchedule[] = [];
107+
for (const item of data) {
108+
const startTime = dayjs(item.KS);
109+
const weekdays = [
110+
'MONDAY',
111+
'TUESDAY',
112+
'WEDNESDAY',
113+
'THURSDAY',
114+
'FRIDAY',
115+
'SATURDAY',
116+
'SUNDAY',
117+
] as const;
118+
for (const index in weekdays) {
119+
const dayKey = weekdays[index]!;
120+
const classes = item[dayKey];
121+
if (classes && classes.length > 0) {
122+
results.push(
123+
...classes.map((cls) => ({
124+
courseId: cls.KCBH,
125+
courseName: cls.KCMC,
126+
teacherName: cls.JSMC,
127+
roomName: cls.JSMC,
128+
startLesson: Number(cls.QSJC),
129+
endLesson: Number(cls.JSJC),
130+
startTime: getStartTimeFromLesson(
131+
Number(cls.QSJC),
132+
startTime.add(Number(index), 'day'),
133+
),
134+
endTime: getEndTimeFromLesson(
135+
Number(cls.JSJC),
136+
startTime.add(Number(index), 'day'),
137+
),
138+
weekDay: Number(cls.XQ),
139+
weekNum: item.ZC,
140+
classId: cls.KTBH,
141+
className: cls.KTMC,
142+
remarks: cls.BZ || '',
143+
targetGrade: cls.MXNJ,
144+
startWeek: cls.QSZC,
145+
endWeek: cls.JSZC,
146+
teachingMethod: cls.SKXS,
147+
semesterId: cls.XQH,
148+
})),
149+
);
150+
}
151+
}
152+
}
153+
154+
return results;
155+
} catch (e) {
156+
console.error('CourseClient.getNormalCourseSchedule error on fetching', e);
157+
throw e;
158+
}
159+
}

index.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,13 @@ export default class HUST {
154154
case Client.news:
155155
return await this.auth.loginONE();
156156
case Client.course:
157-
return await this.auth.loginPhysics();
157+
return (
158+
await Promise.all([
159+
this.auth.loginPhysics(),
160+
this.auth.loginHUBM(),
161+
this.auth.loginHUBS(),
162+
])
163+
).every((item) => item);
158164
default:
159165
throw new Error(`Client ${client} not supported`);
160166
}
@@ -261,7 +267,7 @@ console.log('Initializing HUST SDK...');
261267
const res = await hust.news.getNewsList();
262268
console.log('News List:', res);
263269

264-
const res2 = await hust.course.getPhysicsCourseGrades();
270+
const res2 = await hust.course.getNormalCourseSchedule('20242');
265271
console.log('Course Schedule:', res2);
266272

267273
console.log(`initialized after ${new Date().getTime() - now.getTime()}ms`);

types/clients/course/course.ts

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import type { CourseSchedule } from "./common";
2+
3+
export type NormalCourseScheduleResponseClass = {
4+
/**
5+
* 备注
6+
*/
7+
BZ: string;
8+
/**
9+
* 节次
10+
*/
11+
JC: string;
12+
/**
13+
* 结束节次
14+
*/
15+
JSJC: string;
16+
/**
17+
* 教室名称
18+
*/
19+
JSMC: string;
20+
/**
21+
* 结束周次
22+
*/
23+
JSZC: number;
24+
/**
25+
* 课程编号
26+
*/
27+
KCBH: string;
28+
/**
29+
* 课程名称
30+
*/
31+
KCMC: string;
32+
/**
33+
* 课堂编号
34+
*/
35+
KTBH: string;
36+
/**
37+
* 课堂名称
38+
*/
39+
KTMC: string;
40+
/**
41+
* 面向年级
42+
*/
43+
MXNJ: string;
44+
/**
45+
* 起始节次
46+
*/
47+
QSJC: string;
48+
/**
49+
* 起始周次
50+
*/
51+
QSZC: number;
52+
/**
53+
* 授课形式
54+
*/
55+
SKXS: string;
56+
/**
57+
* 星期几
58+
*/
59+
XQ: string;
60+
/**
61+
* 学期号
62+
*/
63+
XQH: string;
64+
};
65+
66+
export type NormalCourseScheduleResponse = {
67+
/**
68+
* 周次
69+
*/
70+
ZC: number;
71+
/**
72+
* 结束时间
73+
*/
74+
JS: string;
75+
/**
76+
* 开始时间
77+
*/
78+
KS: string;
79+
/**
80+
* 周一
81+
*/
82+
MONDAY: NormalCourseScheduleResponseClass[];
83+
/**
84+
* 周二
85+
*/
86+
TUESDAY: NormalCourseScheduleResponseClass[];
87+
/**
88+
* 周三
89+
*/
90+
WEDNESDAY: NormalCourseScheduleResponseClass[];
91+
/**
92+
* 周四
93+
*/
94+
THURSDAY: NormalCourseScheduleResponseClass[];
95+
/**
96+
* 周五
97+
*/
98+
FRIDAY: NormalCourseScheduleResponseClass[];
99+
/**
100+
* 周六
101+
*/
102+
SATURDAY: NormalCourseScheduleResponseClass[];
103+
/**
104+
* 周日
105+
*/
106+
SUNDAY: NormalCourseScheduleResponseClass[];
107+
}[];
108+
109+
export type NormalCourseSchedule = CourseSchedule & {
110+
/**
111+
* 备注
112+
*/
113+
remarks: string;
114+
/**
115+
* 课堂编号
116+
*/
117+
classId: string;
118+
/**
119+
* 课堂名称
120+
*/
121+
className: string;
122+
/**
123+
* 面向年级
124+
*/
125+
targetGrade: string;
126+
/**
127+
* 起始周次
128+
*/
129+
startWeek: number;
130+
/**
131+
* 结束周次
132+
*/
133+
endWeek: number;
134+
/**
135+
* 授课形式
136+
*/
137+
teachingMethod: string;
138+
/**
139+
* 学期号
140+
*/
141+
semesterId: string;
142+
}

0 commit comments

Comments
 (0)