80 lines
2.2 KiB
Go
80 lines
2.2 KiB
Go
|
|
package service
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"fmt"
|
||
|
|
"log/slog"
|
||
|
|
"strings"
|
||
|
|
|
||
|
|
"schedule_converter/client"
|
||
|
|
"schedule_converter/models"
|
||
|
|
"schedule_converter/parser"
|
||
|
|
apperr "schedule_converter/pkg/errors"
|
||
|
|
|
||
|
|
pb "schedule_converter/proto/runner"
|
||
|
|
)
|
||
|
|
|
||
|
|
var allExamTypes = []models.ExamType{models.ExamTypeFinal, models.ExamTypeMidterm, models.ExamTypeMakeup}
|
||
|
|
|
||
|
|
// GetExams 获取考试安排:登录 → 遍历各考试类型抓取并解析 → 合并 → 转换为 pb 结果。
|
||
|
|
func (s *Service) GetExams(ctx context.Context, req *pb.GetExamsPayload) (*pb.ExamsResultData, error) {
|
||
|
|
log := slog.With("username", req.Username, "semester", req.Semester)
|
||
|
|
|
||
|
|
httpClient, err := s.newAuthenticatedClient(ctx, req.Username, req.Password, "")
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
|
||
|
|
var allExams []models.ExamEntry
|
||
|
|
var lastErr error
|
||
|
|
for _, et := range allExamTypes {
|
||
|
|
data := fmt.Sprintf("xnxq=&kssjd=%s", parser.ExamTypeCode(et))
|
||
|
|
html, ferr := client.FetchHTML(ctx, httpClient, "POST", "/kscx/queryKsForXs", strings.NewReader(data), "application/x-www-form-urlencoded", "")
|
||
|
|
if ferr != nil {
|
||
|
|
log.Warn("获取考试数据失败", "exam_type", string(et), "error", ferr)
|
||
|
|
lastErr = ferr
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
exams, perr := parser.ParseExamHTML(html, et)
|
||
|
|
if perr != nil {
|
||
|
|
log.Warn("解析考试数据失败", "exam_type", string(et), "error", perr)
|
||
|
|
lastErr = perr
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
allExams = append(allExams, exams...)
|
||
|
|
}
|
||
|
|
|
||
|
|
if len(allExams) == 0 && lastErr != nil {
|
||
|
|
return nil, apperr.New("fetch_exams", lastErr, "所有考试类型获取均失败")
|
||
|
|
}
|
||
|
|
|
||
|
|
return &pb.ExamsResultData{
|
||
|
|
StudentId: req.Username,
|
||
|
|
Semester: req.Semester,
|
||
|
|
Exams: convertExams(allExams),
|
||
|
|
}, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// convertExams 将内部考试模型转换为 pb.Exam 列表。
|
||
|
|
func convertExams(exams []models.ExamEntry) []*pb.Exam {
|
||
|
|
result := make([]*pb.Exam, 0, len(exams))
|
||
|
|
for _, e := range exams {
|
||
|
|
examTypeStr := "期末"
|
||
|
|
switch e.Type {
|
||
|
|
case models.ExamTypeMidterm:
|
||
|
|
examTypeStr = "期中"
|
||
|
|
case models.ExamTypeMakeup:
|
||
|
|
examTypeStr = "补考"
|
||
|
|
}
|
||
|
|
result = append(result, &pb.Exam{
|
||
|
|
CourseName: e.Course,
|
||
|
|
ExamType: examTypeStr,
|
||
|
|
Date: e.Date,
|
||
|
|
Time: e.Time,
|
||
|
|
Week: e.Week,
|
||
|
|
Weekday: e.Weekday,
|
||
|
|
})
|
||
|
|
}
|
||
|
|
return result
|
||
|
|
}
|