feat: release undergraduate integration 0.7.0

This commit is contained in:
Codex
2026-10-15 01:14:06 +08:00
parent b28f333720
commit 674df1ceb3
22 changed files with 173 additions and 63 deletions
@@ -26,11 +26,13 @@ class UndergraduateExamAdapter {
UndergraduateExamType? expectedType,
}) {
try {
if (utf8.encode(content).length > 2 * 1024 * 1024)
if (utf8.encode(content).length > 2 * 1024 * 1024) {
throw const FormatException('考试页面超过2MB');
}
final doc = html.parse(content);
if (doc.querySelector('input[type="password"]') != null)
if (doc.querySelector('input[type="password"]') != null) {
throw const FormatException('请先完成学校登录');
}
final form = doc.querySelector('#stdExamTableForm');
final scope = form ?? doc;
final termValues = scope
@@ -58,22 +60,26 @@ class UndergraduateExamAdapter {
final query = Uri.splitQueryString(
m[1]!.replaceFirst(RegExp(r'^&'), ''),
);
if (query['semester.id'] != null)
if (query['semester.id'] != null) {
termValues.add(query['semester.id']!);
if (query['examType.id'] != null)
}
if (query['examType.id'] != null) {
typeValues.add(query['examType.id']!);
}
}
}
if (termValues.length != 1 || typeValues.length != 1)
if (termValues.length != 1 || typeValues.length != 1) {
throw const FormatException('排考结果学期或类型不明确');
}
final term = SchoolTerm(
int.parse(termValues.single),
school: SupportedSchool.uestcUndergraduate,
);
final type = UndergraduateExamType.fromId(int.parse(typeValues.single));
if (expectedTerm != null && expectedTerm != term ||
expectedType != null && expectedType != type)
expectedType != null && expectedType != type) {
throw const FormatException('排考结果与所选学期或类型不一致');
}
Element? table;
for (final candidate in doc.querySelectorAll('table')) {
final cells = candidate
@@ -116,12 +122,14 @@ class UndergraduateExamAdapter {
examTypeId: rowType,
notes: cells[8],
);
if (record.code.isEmpty || record.name.isEmpty)
if (record.code.isEmpty || record.name.isEmpty) {
throw const FormatException('考试课程缺失');
}
records.putIfAbsent(record.undergraduateKey, () => record);
}
if (records.isEmpty && !explicitEmpty)
if (records.isEmpty && !explicitEmpty) {
throw const FormatException('尚未识别到明确的排考结果');
}
return ExamSchedule.fromJson(
ExamSchedule(
semesterLabel: term.label,
@@ -158,14 +166,16 @@ class UndergraduateExamAdapter {
part.termId != '${query.term.id}' ||
part.requestedExamTypes.length != 1 ||
!expected.contains(part.requestedExamTypes.single) ||
!seen.add(part.requestedExamTypes.single))
!seen.add(part.requestedExamTypes.single)) {
throw const FormatException('考试查询批次不一致');
}
for (final record in part.records) {
records.putIfAbsent(record.undergraduateKey, () => record);
}
}
if (seen.length != expected.length || records.length > 500)
if (seen.length != expected.length || records.length > 500) {
throw const FormatException('考试未全部读取完成或记录超限');
}
return ExamSchedule.fromJson(
ExamSchedule(
semesterLabel: query.term.label,