@robertying/thu-learn-lib 0.0.0-stage → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +324 -2
  3. package/lib/auth.d.ts +11 -0
  4. package/lib/auth.d.ts.map +1 -0
  5. package/lib/auth.js +99 -0
  6. package/lib/auth.js.map +1 -0
  7. package/lib/calendar.d.ts +16 -0
  8. package/lib/calendar.d.ts.map +1 -0
  9. package/lib/calendar.js +81 -0
  10. package/lib/calendar.js.map +1 -0
  11. package/lib/contents.d.ts +9 -0
  12. package/lib/contents.d.ts.map +1 -0
  13. package/lib/contents.js +52 -0
  14. package/lib/contents.js.map +1 -0
  15. package/lib/courses.d.ts +9 -0
  16. package/lib/courses.d.ts.map +1 -0
  17. package/lib/courses.js +82 -0
  18. package/lib/courses.js.map +1 -0
  19. package/lib/discussions.d.ts +11 -0
  20. package/lib/discussions.d.ts.map +1 -0
  21. package/lib/discussions.js +56 -0
  22. package/lib/discussions.js.map +1 -0
  23. package/lib/favorites.d.ts +35 -0
  24. package/lib/favorites.d.ts.map +1 -0
  25. package/lib/favorites.js +150 -0
  26. package/lib/favorites.js.map +1 -0
  27. package/lib/files.d.ts +13 -0
  28. package/lib/files.d.ts.map +1 -0
  29. package/lib/files.js +167 -0
  30. package/lib/files.js.map +1 -0
  31. package/lib/homework.d.ts +9 -0
  32. package/lib/homework.d.ts.map +1 -0
  33. package/lib/homework.js +193 -0
  34. package/lib/homework.js.map +1 -0
  35. package/lib/index.d.ts +105 -0
  36. package/lib/index.d.ts.map +1 -0
  37. package/lib/index.js +181 -0
  38. package/lib/index.js.map +1 -0
  39. package/lib/notices.d.ts +6 -0
  40. package/lib/notices.d.ts.map +1 -0
  41. package/lib/notices.js +84 -0
  42. package/lib/notices.js.map +1 -0
  43. package/lib/questionnaires.d.ts +7 -0
  44. package/lib/questionnaires.d.ts.map +1 -0
  45. package/lib/questionnaires.js +62 -0
  46. package/lib/questionnaires.js.map +1 -0
  47. package/lib/request.d.ts +31 -0
  48. package/lib/request.d.ts.map +1 -0
  49. package/lib/request.js +90 -0
  50. package/lib/request.js.map +1 -0
  51. package/lib/types.d.ts +392 -0
  52. package/lib/types.d.ts.map +1 -0
  53. package/lib/types.js +97 -0
  54. package/lib/types.js.map +1 -0
  55. package/lib/urls.d.ts +78 -0
  56. package/lib/urls.d.ts.map +1 -0
  57. package/lib/urls.js +160 -0
  58. package/lib/urls.js.map +1 -0
  59. package/lib/user.d.ts +7 -0
  60. package/lib/user.d.ts.map +1 -0
  61. package/lib/user.js +22 -0
  62. package/lib/user.js.map +1 -0
  63. package/lib/utils.d.ts +13 -0
  64. package/lib/utils.d.ts.map +1 -0
  65. package/lib/utils.js +115 -0
  66. package/lib/utils.js.map +1 -0
  67. package/package.json +67 -4
  68. package/src/auth.ts +121 -0
  69. package/src/calendar.ts +102 -0
  70. package/src/contents.ts +67 -0
  71. package/src/courses.ts +97 -0
  72. package/src/discussions.ts +80 -0
  73. package/src/favorites.ts +167 -0
  74. package/src/files.ts +197 -0
  75. package/src/homework.ts +279 -0
  76. package/src/index.ts +282 -0
  77. package/src/notices.ts +110 -0
  78. package/src/questionnaires.ts +76 -0
  79. package/src/request.ts +101 -0
  80. package/src/types.ts +445 -0
  81. package/src/urls.ts +257 -0
  82. package/src/user.ts +28 -0
  83. package/src/utils.ts +120 -0
package/src/types.ts ADDED
@@ -0,0 +1,445 @@
1
+ import type { CookieJar } from 'tough-cookie';
2
+
3
+ export type Fetch = typeof globalThis.fetch;
4
+ export type Credential = {
5
+ username?: string;
6
+ password?: string;
7
+ fingerPrint?: string;
8
+ fingerGenPrint?: string;
9
+ fingerGenPrint3?: string;
10
+ };
11
+ export type CredentialProvider = () => Credential | Promise<Credential>;
12
+ export type HelperConfig = {
13
+ provider?: CredentialProvider;
14
+ fetch?: Fetch;
15
+ cookieJar?: CookieJar;
16
+ generatePreviewUrlForFirstPage?: boolean;
17
+ };
18
+
19
+ export enum FailReason {
20
+ NO_CREDENTIAL = 'no credential provided',
21
+ ERROR_FETCH_FROM_ID = 'could not fetch ticket from id.tsinghua.edu.cn',
22
+ BAD_CREDENTIAL = 'bad credential',
23
+ ERROR_ROAMING = 'could not roam to learn.tsinghua.edu.cn',
24
+ NOT_LOGGED_IN = 'not logged in or login timeout',
25
+ NOT_IMPLEMENTED = 'not implemented',
26
+ INVALID_RESPONSE = 'invalid response',
27
+ UNEXPECTED_STATUS = 'unexpected status',
28
+ OPERATION_FAILED = 'operation failed',
29
+ ERROR_SETTING_COOKIES = 'could not set cookies',
30
+ }
31
+
32
+ export interface ApiError {
33
+ reason: FailReason;
34
+ extra?: unknown;
35
+ }
36
+
37
+ export enum SemesterType {
38
+ FALL = 'fall',
39
+ SPRING = 'spring',
40
+ SUMMER = 'summer',
41
+ UNKNOWN = '',
42
+ }
43
+
44
+ export enum ContentType {
45
+ NOTIFICATION = 'notification',
46
+ FILE = 'file',
47
+ HOMEWORK = 'homework',
48
+ DISCUSSION = 'discussion',
49
+ QUESTION = 'question',
50
+ QUESTIONNAIRE = 'questionnaire',
51
+ }
52
+
53
+ interface IUserInfo {
54
+ name: string;
55
+ department: string;
56
+ }
57
+
58
+ export type UserInfo = IUserInfo;
59
+
60
+ interface ISemesterInfo {
61
+ id: string;
62
+ startDate: string;
63
+ endDate: string;
64
+ startYear: number;
65
+ endYear: number;
66
+ type: SemesterType;
67
+ }
68
+
69
+ export type SemesterInfo = ISemesterInfo;
70
+
71
+ export enum CourseType {
72
+ STUDENT = 'student',
73
+ TEACHER = 'teacher',
74
+ }
75
+
76
+ interface ICourseInfo {
77
+ id: string;
78
+ name: string;
79
+ chineseName: string;
80
+ englishName: string;
81
+ timeAndLocation: string[];
82
+ url: string;
83
+ teacherName: string;
84
+ teacherNumber: string;
85
+ courseNumber: string;
86
+ courseIndex: number;
87
+ courseType: CourseType;
88
+ }
89
+
90
+ export type CourseInfo = ICourseInfo;
91
+
92
+ interface IRemoteFile {
93
+ id: string;
94
+ name: string;
95
+ downloadUrl: string;
96
+ previewUrl: string;
97
+ size: string;
98
+ }
99
+
100
+ export type RemoteFile = IRemoteFile;
101
+
102
+ export interface INotification {
103
+ id: string;
104
+ title: string;
105
+ content: string;
106
+ hasRead: boolean;
107
+ url: string;
108
+ markedImportant: boolean;
109
+ publishTime: string;
110
+ publisher: string;
111
+ expireTime?: string;
112
+ isFavorite: boolean;
113
+ comment?: string;
114
+ }
115
+
116
+ export interface INotificationDetail {
117
+ attachment?: RemoteFile;
118
+ }
119
+
120
+ export type Notification = INotification & INotificationDetail;
121
+
122
+ interface IFileCategory {
123
+ id: string;
124
+ title: string;
125
+ creationTime: Date;
126
+ }
127
+
128
+ export type FileCategory = IFileCategory;
129
+
130
+ interface IFile {
131
+ /** previously `id2` */
132
+ id: string;
133
+ /** previously `id` */
134
+ fileId: string;
135
+ /** note: will be unset when calling `getFileListByCategory` */
136
+ category?: FileCategory;
137
+ /** size in byte */
138
+ rawSize: number;
139
+ /** inaccurate size description (like '1M') */
140
+ size: string;
141
+ title: string;
142
+ description: string;
143
+ uploadTime: string;
144
+ publishTime: string;
145
+ downloadUrl: string;
146
+ /** preview is not supported on all types of files, check before use */
147
+ previewUrl: string;
148
+ isNew: boolean;
149
+ markedImportant: boolean;
150
+ visitCount: number;
151
+ downloadCount: number;
152
+ fileType: string;
153
+ /** for compatibility */
154
+ remoteFile: RemoteFile;
155
+ /** could not get favorite or comment info when using `getFileList` or in TA mode */
156
+ isFavorite?: boolean;
157
+ comment?: string;
158
+ }
159
+
160
+ export type File = IFile;
161
+
162
+ export interface IHomeworkStatus {
163
+ submitted: boolean;
164
+ graded: boolean;
165
+ }
166
+
167
+ export enum HomeworkGradeLevel {
168
+ /** 已阅 */
169
+ CHECKED = 'checked',
170
+ A_PLUS = 'A+',
171
+ A = 'A',
172
+ A_MINUS = 'A-',
173
+ B_PLUS = 'B+',
174
+ /** 优秀 */
175
+ DISTINCTION = 'distinction',
176
+ B = 'B',
177
+ B_MINUS = 'B-',
178
+ C_PLUS = 'C+',
179
+ C = 'C',
180
+ C_MINUS = 'C-',
181
+ G = 'G',
182
+ D_PLUS = 'D+',
183
+ D = 'D',
184
+ /** 免课 */
185
+ EXEMPTED_COURSE = 'exempted course',
186
+ P = 'P',
187
+ EX = 'EX',
188
+ /** 免修 */
189
+ EXEMPTION = 'exemption',
190
+ /** 通过 */
191
+ PASS = 'pass',
192
+ /** 不通过 */
193
+ FAILURE = 'failure',
194
+ W = 'W',
195
+ I = 'I',
196
+ /** 缓考 */
197
+ INCOMPLETE = 'incomplete',
198
+ NA = 'NA',
199
+ F = 'F',
200
+ }
201
+
202
+ export interface IHomework extends IHomeworkStatus {
203
+ id: string;
204
+ /** @deprecated use `id` */
205
+ studentHomeworkId: string;
206
+ baseId: string;
207
+ title: string;
208
+ deadline: string;
209
+ lateSubmissionDeadline?: string;
210
+ url: string;
211
+ completionType: HomeworkCompletionType;
212
+ submissionType: HomeworkSubmissionType;
213
+ submitUrl: string;
214
+ submitTime?: string;
215
+ isLateSubmission: boolean;
216
+ grade?: number;
217
+ /** some homework has levels but not grades, like A/B/.../F */
218
+ gradeLevel?: HomeworkGradeLevel;
219
+ gradeTime?: string;
220
+ graderName?: string;
221
+ gradeContent?: string;
222
+ isFavorite: boolean;
223
+ favoriteTime?: string;
224
+ comment?: string;
225
+ excellentHomeworkList?: ExcellentHomework[];
226
+ }
227
+
228
+ export interface IHomeworkDetail {
229
+ description?: string;
230
+ /** attachment from teacher */
231
+ attachment?: RemoteFile;
232
+ /** answer from teacher */
233
+ answerContent?: string;
234
+ answerAttachment?: RemoteFile;
235
+ /** submitted content from student */
236
+ submittedContent?: string;
237
+ submittedAttachment?: RemoteFile;
238
+ /** grade from teacher */
239
+ gradeAttachment?: RemoteFile;
240
+ }
241
+
242
+ export type Homework = IHomework & IHomeworkDetail;
243
+
244
+ export enum HomeworkCompletionType {
245
+ INDIVIDUAL = 1,
246
+ GROUP = 2,
247
+ }
248
+
249
+ export enum HomeworkSubmissionType {
250
+ WEB_LEARNING = 2,
251
+ OFFLINE = 0,
252
+ }
253
+
254
+ export interface IExcellentHomework {
255
+ id: string;
256
+ baseId: string;
257
+ title: string;
258
+ url: string;
259
+ completionType: HomeworkCompletionType;
260
+ author: {
261
+ id: string;
262
+ name: string;
263
+ anonymous: boolean;
264
+ };
265
+ }
266
+
267
+ export type ExcellentHomework = IExcellentHomework & IHomeworkDetail;
268
+
269
+ export interface IHomeworkTA {
270
+ id: string;
271
+ index: number;
272
+ title: string;
273
+ description: string;
274
+ publisherId: string;
275
+ publishTime: string;
276
+ startTime: string;
277
+ deadline: string;
278
+ lateSubmissionDeadline?: string;
279
+ url: string;
280
+ completionType: HomeworkCompletionType;
281
+ submissionType: HomeworkSubmissionType;
282
+ gradedCount: number;
283
+ submittedCount: number;
284
+ unsubmittedCount: number;
285
+ }
286
+
287
+ export type HomeworkTA = IHomeworkTA;
288
+
289
+ export interface IHomeworkSubmitAttachment {
290
+ filename: string;
291
+ content: Blob;
292
+ }
293
+
294
+ export interface IDiscussionBase {
295
+ id: string;
296
+ title: string;
297
+ publisherName: string;
298
+ publishTime: string;
299
+ lastReplierName: string;
300
+ lastReplyTime: string;
301
+ visitCount: number;
302
+ replyCount: number;
303
+ isFavorite: boolean;
304
+ comment?: string;
305
+ }
306
+
307
+ interface IDiscussion extends IDiscussionBase {
308
+ url: string;
309
+ boardId: string;
310
+ }
311
+
312
+ export type Discussion = IDiscussion;
313
+
314
+ interface IQuestion extends IDiscussionBase {
315
+ url: string;
316
+ question: string;
317
+ }
318
+
319
+ export type Question = IQuestion;
320
+
321
+ export enum QuestionnaireDetailType {
322
+ SINGLE = 'dnx',
323
+ MULTI = 'dox',
324
+ TEXT = 'wd',
325
+ }
326
+
327
+ export interface QuestionnaireDetail {
328
+ id: string;
329
+ index: number;
330
+ type: QuestionnaireDetailType;
331
+ required: boolean;
332
+ title: string;
333
+ score?: number;
334
+ options?: {
335
+ id: string;
336
+ index: number;
337
+ title: string;
338
+ }[];
339
+ }
340
+
341
+ export enum QuestionnaireType {
342
+ VOTE = 'tp',
343
+ FORM = 'tb',
344
+ SURVEY = 'wj',
345
+ }
346
+
347
+ export interface IQuestionnaire {
348
+ id: string;
349
+ type: QuestionnaireType;
350
+ title: string;
351
+ startTime: string;
352
+ endTime: string;
353
+ uploadTime: string;
354
+ uploaderId: string;
355
+ uploaderName: string;
356
+ submitTime?: string;
357
+ isFavorite: boolean;
358
+ comment?: string;
359
+ url: string;
360
+ detail: QuestionnaireDetail[];
361
+ }
362
+
363
+ export type Questionnaire = IQuestionnaire;
364
+
365
+ export type ContentTypeMap = {
366
+ [ContentType.NOTIFICATION]: Notification;
367
+ [ContentType.FILE]: File;
368
+ [ContentType.HOMEWORK]: Homework;
369
+ [ContentType.DISCUSSION]: Discussion;
370
+ [ContentType.QUESTION]: Question;
371
+ [ContentType.QUESTIONNAIRE]: Questionnaire;
372
+ };
373
+
374
+ interface ICourseContent<T extends ContentType> {
375
+ [id: string]: ContentTypeMap[T][];
376
+ }
377
+
378
+ export type CourseContent<T extends ContentType = ContentType> = ICourseContent<T>;
379
+
380
+ interface IFavoriteItem {
381
+ id: string;
382
+ type: ContentType;
383
+ title: string;
384
+ time: string;
385
+ state: string;
386
+ /** extra message. For homework, this will be deadline (plus score if graded). It's too flexible and hard to parse so we leave it as is. */
387
+ extra?: string;
388
+ semesterId: string;
389
+ courseId: string;
390
+ pinned: boolean;
391
+ pinnedTime?: string;
392
+ comment?: string;
393
+ addedTime: string;
394
+ /** for reference */
395
+ itemId: string;
396
+ }
397
+
398
+ export type FavoriteItem = IFavoriteItem;
399
+
400
+ interface ICommentItem {
401
+ id: string;
402
+ type: ContentType;
403
+ content: string;
404
+ contentHTML: string;
405
+ title: string;
406
+ semesterId: string;
407
+ courseId: string;
408
+ commentTime: string;
409
+ /** for reference */
410
+ itemId: string;
411
+ }
412
+
413
+ export type CommentItem = ICommentItem;
414
+
415
+ export interface CalendarEvent {
416
+ location: string;
417
+ status: string;
418
+ startTime: string;
419
+ endTime: string;
420
+ date: string;
421
+ courseName: string;
422
+ }
423
+
424
+ export interface CalendarOptions {
425
+ /** use the graduate calendar instead of the undergraduate one */
426
+ graduate?: boolean;
427
+ }
428
+
429
+ /** an inclusive date range, in yyyymmdd format */
430
+ export interface CalendarRange {
431
+ startDate: string;
432
+ endDate: string;
433
+ }
434
+
435
+ export interface CalendarResult {
436
+ /** events of every window that succeeded, in date order */
437
+ events: CalendarEvent[];
438
+ /** windows that failed even after a retry; empty when the whole range was fetched */
439
+ failedRanges: CalendarRange[];
440
+ }
441
+
442
+ export enum Language {
443
+ ZH = 'zh',
444
+ EN = 'en',
445
+ }
package/src/urls.ts ADDED
@@ -0,0 +1,257 @@
1
+ import { FormData } from 'node-fetch-native';
2
+ import type { ContentType, IHomeworkSubmitAttachment, QuestionnaireType } from './types.ts';
3
+ import { CourseType, Language } from './types.ts';
4
+ import { CONTENT_TYPE_MAP, getMkFromType } from './utils.ts';
5
+
6
+ export const ID_PREFIX = 'https://id.tsinghua.edu.cn';
7
+ export const LEARN_PREFIX = 'https://learn.tsinghua.edu.cn';
8
+ export const REGISTRAR_PREFIX = 'https://zhjw.cic.tsinghua.edu.cn';
9
+
10
+ const MAX_SIZE = 200;
11
+
12
+ export const ID_LOGIN = () => 'https://id.tsinghua.edu.cn/do/off/ui/auth/login/form/bb5df85216504820be7bba2b0ae1535b/0';
13
+
14
+ export const ID_LOGIN_CHECK = () => 'https://id.tsinghua.edu.cn/do/off/ui/auth/login/check';
15
+
16
+ export const LEARN_AUTH_ROAM = (ticket: string) =>
17
+ `${LEARN_PREFIX}/b/j_spring_security_thauth_roaming_entry?ticket=${ticket}`;
18
+
19
+ export const LEARN_LOGOUT = () => `${LEARN_PREFIX}/f/j_spring_security_logout`;
20
+
21
+ export const LEARN_HOMEPAGE = (courseType: CourseType) => {
22
+ if (courseType === CourseType.STUDENT) {
23
+ return `${LEARN_PREFIX}/f/wlxt/index/course/student/`;
24
+ } else {
25
+ return `${LEARN_PREFIX}/f/wlxt/index/course/teacher/`;
26
+ }
27
+ };
28
+
29
+ export const LEARN_STUDENT_COURSE_LIST_PAGE = () => `${LEARN_PREFIX}/f/wlxt/index/course/student/`;
30
+
31
+ export const LEARN_SEMESTER_LIST = () => `${LEARN_PREFIX}/b/wlxt/kc/v_wlkc_xs_xktjb_coassb/queryxnxq`;
32
+
33
+ export const LEARN_CURRENT_SEMESTER = () => `${LEARN_PREFIX}/b/kc/zhjw_v_code_xnxq/getCurrentAndNextSemester`;
34
+
35
+ export const LEARN_COURSE_LIST = (semester: string, courseType: CourseType, lang: Language) =>
36
+ courseType === CourseType.STUDENT
37
+ ? `${LEARN_PREFIX}/b/wlxt/kc/v_wlkc_xs_xkb_kcb_extend/student/loadCourseBySemesterId/${semester}/${lang}`
38
+ : `${LEARN_PREFIX}/b/kc/v_wlkc_kcb/queryAsorCoCourseList/${semester}/0`;
39
+
40
+ export const LEARN_COURSE_PAGE = (courseID: string, courseType: CourseType) =>
41
+ `${LEARN_PREFIX}/f/wlxt/index/course/${courseType}/course?wlkcid=${courseID}`;
42
+
43
+ export const LEARN_COURSE_TIME_LOCATION = (courseID: string) =>
44
+ `${LEARN_PREFIX}/b/kc/v_wlkc_xk_sjddb/detail?id=${courseID}`;
45
+
46
+ export const LEARN_FILE_LIST = (courseID: string, courseType: CourseType) =>
47
+ courseType === CourseType.STUDENT
48
+ ? `${LEARN_PREFIX}/b/wlxt/kj/wlkc_kjxxb/student/kjxxbByWlkcidAndSizeForStudent?wlkcid=${courseID}&size=${MAX_SIZE}`
49
+ : `${LEARN_PREFIX}/b/wlxt/kj/v_kjxxb_wjwjb/teacher/queryByWlkcid?wlkcid=${courseID}&size=${MAX_SIZE}`;
50
+
51
+ export const LEARN_FILE_CATEGORY_LIST = (courseID: string, courseType: CourseType) =>
52
+ `${LEARN_PREFIX}/b/wlxt/kj/wlkc_kjflb/${courseType}/pageList?wlkcid=${courseID}`;
53
+
54
+ export const LEARN_FILE_LIST_BY_CATEGORY_STUDENT = (courseID: string, categoryId: string) =>
55
+ `${LEARN_PREFIX}/b/wlxt/kj/wlkc_kjxxb/student/kjxxb/${courseID}/${categoryId}`;
56
+
57
+ export const LEARN_FILE_LIST_BY_CATEGORY_TEACHER = `${LEARN_PREFIX}/b/wlxt/kj/v_kjxxb_wjwjb/teacher/pageList`;
58
+
59
+ export const LEARN_FILE_LIST_BY_CATEGORY_TEACHER_FORM_DATA = (courseID: string, categoryId: string) => {
60
+ const form = new FormData();
61
+ form.append(
62
+ 'aoData',
63
+ JSON.stringify([
64
+ { name: 'wlkcid', value: courseID },
65
+ { name: 'kjflid', value: categoryId },
66
+ ]),
67
+ );
68
+ return form;
69
+ };
70
+
71
+ export const LEARN_FILE_DOWNLOAD = (fileID: string, courseType: CourseType) =>
72
+ `${LEARN_PREFIX}/b/wlxt/kj/wlkc_kjxxb/${courseType}/downloadFile?sfgk=0&wjid=${fileID}`;
73
+
74
+ export const LEARN_FILE_PREVIEW = (type: ContentType, fileID: string, courseType: CourseType, firstPageOnly = false) =>
75
+ `${LEARN_PREFIX}/f/wlxt/kc/wj_wjb/${courseType}/beforePlay?wjid=${fileID}&mk=${getMkFromType(
76
+ type,
77
+ )}&browser=-1&sfgk=0&pageType=${firstPageOnly ? 'first' : 'all'}`;
78
+
79
+ export const LEARN_NOTIFICATION_LIST = (courseType: CourseType, expired: boolean) =>
80
+ `${LEARN_PREFIX}/b/wlxt/kcgg/wlkc_ggb/` +
81
+ (courseType === CourseType.STUDENT ? 'student/pageListXsby' : 'teacher/pageListby') +
82
+ (expired ? 'Ygq' : 'Wgq');
83
+
84
+ export const LEARN_NOTIFICATION_DETAIL = (courseID: string, notificationID: string, courseType: CourseType) =>
85
+ courseType === CourseType.STUDENT
86
+ ? `${LEARN_PREFIX}/f/wlxt/kcgg/wlkc_ggb/student/beforeViewXs?wlkcid=${courseID}&id=${notificationID}`
87
+ : `${LEARN_PREFIX}/f/wlxt/kcgg/wlkc_ggb/teacher/beforeViewJs?wlkcid=${courseID}&id=${notificationID}`;
88
+
89
+ export const LEARN_NOTIFICATION_EDIT = (courseType: CourseType): string =>
90
+ `${LEARN_PREFIX}/b/wlxt/kcgg/wlkc_ggb/${courseType}/editKcgg`;
91
+
92
+ export const LEARN_HOMEWORK_LIST_NEW = `${LEARN_PREFIX}/b/wlxt/kczy/zy/student/zyListWj`;
93
+ export const LEARN_HOMEWORK_LIST_SUBMITTED = `${LEARN_PREFIX}/b/wlxt/kczy/zy/student/zyListYjwg`;
94
+ export const LEARN_HOMEWORK_LIST_GRADED = `${LEARN_PREFIX}/b/wlxt/kczy/zy/student/zyListYpg`;
95
+ export const LEARN_HOMEWORK_LIST_EXCELLENT = `${LEARN_PREFIX}/b/wlxt/kczy/zy/student/yxzylist`;
96
+ export const LEARN_HOMEWORK_LIST_SOURCE = [
97
+ {
98
+ url: LEARN_HOMEWORK_LIST_NEW,
99
+ status: {
100
+ submitted: false,
101
+ graded: false,
102
+ },
103
+ },
104
+ {
105
+ url: LEARN_HOMEWORK_LIST_SUBMITTED,
106
+ status: {
107
+ submitted: true,
108
+ graded: false,
109
+ },
110
+ },
111
+ {
112
+ url: LEARN_HOMEWORK_LIST_GRADED,
113
+ status: {
114
+ submitted: true,
115
+ graded: true,
116
+ },
117
+ },
118
+ ];
119
+
120
+ export const LEARN_HOMEWORK_PAGE = (courseID: string, id: string) =>
121
+ `${LEARN_PREFIX}/f/wlxt/kczy/zy/student/viewCj?wlkcid=${courseID}&xszyid=${id}`;
122
+
123
+ export const LEARN_HOMEWORK_EXCELLENT_PAGE = (courseID: string, id: string) =>
124
+ `${LEARN_PREFIX}/f/wlxt/kczy/zy/student/viewYxzy?wlkcid=${courseID}&xszyid=${id}`;
125
+
126
+ export const LEARN_HOMEWORK_DETAIL = `${LEARN_PREFIX}/b/wlxt/kczy/zy/student/detail`;
127
+
128
+ export const LEARN_HOMEWORK_DETAIL_FORM_DATA = (baseId: string) => {
129
+ const form = new FormData();
130
+ form.append('id', baseId);
131
+ return form;
132
+ };
133
+
134
+ export const LEARN_HOMEWORK_DOWNLOAD = (courseID: string, attachmentID: string) =>
135
+ `${LEARN_PREFIX}/b/wlxt/kczy/zy/student/downloadFile/${courseID}/${attachmentID}`;
136
+
137
+ export const LEARN_HOMEWORK_SUBMIT_PAGE = (courseID: string, id: string) =>
138
+ `${LEARN_PREFIX}/f/wlxt/kczy/zy/student/tijiao?wlkcid=${courseID}&xszyid=${id}`;
139
+
140
+ export const LEARN_HOMEWORK_SUBMIT = () => `${LEARN_PREFIX}/b/wlxt/kczy/zy/student/tjzy`;
141
+
142
+ export const LEARN_HOMEWORK_SUBMIT_FORM_DATA = (
143
+ id: string,
144
+ content = '',
145
+ attachment?: IHomeworkSubmitAttachment,
146
+ removeAttachment = false,
147
+ ) => {
148
+ const form = new FormData();
149
+ form.append('xszyid', id);
150
+ form.append('zynr', content ?? '');
151
+ if (attachment) form.append('fileupload', attachment.content, attachment.filename);
152
+ else form.append('fileupload', 'undefined');
153
+ if (removeAttachment) form.append('isDeleted', '1');
154
+ else form.append('isDeleted', '0');
155
+ return form;
156
+ };
157
+
158
+ export const LEARN_HOMEWORK_LIST_TEACHER = `${LEARN_PREFIX}/b/wlxt/kczy/zy/teacher/pageList`;
159
+
160
+ export const LEARN_HOMEWORK_DETAIL_TEACHER = (courseID: string, homeworkID: string) =>
161
+ `${LEARN_PREFIX}/f/wlxt/kczy/xszy/teacher/beforePageList?zyid=${homeworkID}&wlkcid=${courseID}`;
162
+
163
+ export const LEARN_DISCUSSION_LIST = (courseID: string, courseType: CourseType) =>
164
+ `${LEARN_PREFIX}/b/wlxt/bbs/bbs_tltb/${courseType}/kctlList?wlkcid=${courseID}&size=${MAX_SIZE}`;
165
+
166
+ export const LEARN_DISCUSSION_DETAIL = (
167
+ courseID: string,
168
+ boardID: string,
169
+ discussionID: string,
170
+ courseType: CourseType,
171
+ tabId = 1,
172
+ ) =>
173
+ `${LEARN_PREFIX}/f/wlxt/bbs/bbs_tltb/${courseType}/viewTlById?wlkcid=${courseID}&id=${discussionID}&tabbh=${tabId}&bqid=${boardID}`;
174
+
175
+ export const LEARN_QUESTION_LIST_ANSWERED = (courseID: string, courseType: CourseType) =>
176
+ `${LEARN_PREFIX}/b/wlxt/bbs/bbs_tltb/${courseType}/kcdyList?wlkcid=${courseID}&size=${MAX_SIZE}`;
177
+
178
+ export const LEARN_QUESTION_DETAIL = (courseID: string, questionID: string, courseType: CourseType) =>
179
+ courseType === CourseType.STUDENT
180
+ ? `${LEARN_PREFIX}/f/wlxt/bbs/bbs_kcdy/student/viewDyById?wlkcid=${courseID}&id=${questionID}`
181
+ : `${LEARN_PREFIX}/f/wlxt/bbs/bbs_kcdy/teacher/beforeEditDy?wlkcid=${courseID}&id=${questionID}`;
182
+
183
+ export const LEARN_QNR_LIST_ONGOING = `${LEARN_PREFIX}/b/wlxt/kcwj/wlkc_wjb/student/pageListWks`;
184
+ export const LEARN_QNR_LIST_ENDED = `${LEARN_PREFIX}/b/wlxt/kcwj/wlkc_wjb/student/pageListYjs`;
185
+ /** Note: This page is accessible even with an invalid `qnrID` as long as you have access to the given `courseID`. */
186
+ export const LEARN_QNR_SUBMIT_PAGE = (courseID: string, qnrID: string, type: QuestionnaireType) =>
187
+ `${LEARN_PREFIX}/f/wlxt/kcwj/wlkc_wjb/student/beforeAdd?wlkcid=${courseID}&wjid=${qnrID}&wjlx=${type}&jswj=no`;
188
+ export const LEARN_QNR_DETAIL = `${LEARN_PREFIX}/b/wlxt/kcwj/wlkc_wjb/student/getWjnr`;
189
+
190
+ export const LEARN_QNR_DETAIL_FORM = (courseID: string, qnrID: string) => {
191
+ const form = new FormData();
192
+ form.append('wlkcid', courseID);
193
+ form.append('wjid', qnrID);
194
+ return form;
195
+ };
196
+
197
+ export const WebsiteShowLanguage = {
198
+ [Language.ZH]: 'zh_CN',
199
+ [Language.EN]: 'en_US',
200
+ };
201
+
202
+ export const LEARN_WEBSITE_LANGUAGE = (lang: Language) =>
203
+ `${LEARN_PREFIX}/f/wlxt/common/language?websiteShowLanguage=${WebsiteShowLanguage[lang]}`;
204
+
205
+ export const LEARN_FAVORITE_ADD = (type: ContentType, id: string) =>
206
+ `${LEARN_PREFIX}/b/xt/wlkc_xsscb/student/add?ywid=${id}&ywlx=${CONTENT_TYPE_MAP.get(type)}`;
207
+
208
+ export const LEARN_FAVORITE_REMOVE = (id: string) => `${LEARN_PREFIX}/b/xt/wlkc_xsscb/student/delete?ywid=${id}`;
209
+
210
+ export const LEARN_FAVORITE_LIST = (type?: ContentType) =>
211
+ `${LEARN_PREFIX}/b/xt/wlkc_xsscb/student/pageList?ywlx=${type ? CONTENT_TYPE_MAP.get(type) : 'ALL'}`;
212
+
213
+ export const LEARN_FAVORITE_PIN = `${LEARN_PREFIX}/b/xt/wlkc_xsscb/student/addZd`;
214
+
215
+ export const LEARN_FAVORITE_UNPIN = `${LEARN_PREFIX}/b/xt/wlkc_xsscb/student/delZd`;
216
+
217
+ export const LEARN_FAVORITE_PIN_UNPIN_FORM_DATA = (id: string) => {
218
+ const form = new FormData();
219
+ form.append('ywid', id);
220
+ return form;
221
+ };
222
+
223
+ export const LEARN_COMMENT_SET = `${LEARN_PREFIX}/b/wlxt/xt/wlkc_xsbjb/add`;
224
+
225
+ export const LEARN_COMMENT_SET_FORM_DATA = (type: ContentType, id: string, content: string) => {
226
+ const form = new FormData();
227
+ form.append('ywlx', CONTENT_TYPE_MAP.get(type) ?? '');
228
+ form.append('ywid', id);
229
+ form.append('bznr', content);
230
+ return form;
231
+ };
232
+
233
+ export const LEARN_COMMENT_LIST = (type?: ContentType) =>
234
+ `${LEARN_PREFIX}/b/wlxt/xt/wlkc_xsbjb/student/pageList?ywlx=${type ? CONTENT_TYPE_MAP.get(type) : 'ALL'}`;
235
+
236
+ export const LEARN_PAGE_LIST_FORM_DATA = (courseID?: string) => {
237
+ const form = new FormData();
238
+ form.append('aoData', JSON.stringify(courseID ? [{ name: 'wlkcid', value: courseID }] : []));
239
+ return form;
240
+ };
241
+
242
+ export const LEARN_SORT_COURSES = `${LEARN_PREFIX}/b/wlxt/kc/wlkc_kcpxb/addorUpdate`;
243
+
244
+ export const REGISTRAR_TICKET_FORM_DATA = () => {
245
+ const form = new FormData();
246
+ form.append('appId', 'ALL_ZHJW');
247
+ return form;
248
+ };
249
+
250
+ export const REGISTRAR_TICKET = () => `${LEARN_PREFIX}/b/wlxt/common/auth/gnt`;
251
+
252
+ export const REGISTRAR_AUTH = (ticket: string) => `${REGISTRAR_PREFIX}/j_acegi_login.do?url=/&ticket=${ticket}`;
253
+
254
+ export const REGISTRAR_CALENDAR = (startDate: string, endDate: string, graduate = false, callbackName = 'unknown') =>
255
+ `${REGISTRAR_PREFIX}/jxmh_out.do?m=${
256
+ graduate ? 'yjs' : 'bks'
257
+ }_jxrl_all&p_start_date=${startDate}&p_end_date=${endDate}&jsoncallback=${callbackName}`;