package service import ( "context" "log/slog" "schedule_converter/client" "schedule_converter/parser" apperr "schedule_converter/pkg/errors" pb "schedule_converter/proto/runner" ) const cetQueryPath = "/sljcjcx/sljcjcxInit" // GetCET 获取四六级成绩:登录 → 请求四六级查询结果页 → 解析 → 转换为 pb 结果。 func (s *Service) GetCET(ctx context.Context, req *pb.GetCetPayload) (*pb.CetResultData, error) { log := slog.With("username", req.Username) httpClient, err := s.newAuthenticatedClient(ctx, req.Username, req.Password, "") if err != nil { return nil, err } html, err := client.FetchHTML(ctx, httpClient, "GET", cetQueryPath, nil, "", "") if err != nil { return nil, apperr.New("fetch_cet", err, "获取四六级成绩页面失败") } cetResult, err := parser.ParseCETHTML(html) if err != nil { return nil, apperr.New("parse_cet", err, "解析四六级成绩失败") } log.Info("四六级成绩获取成功", "score_count", len(cetResult.Scores)) return &pb.CetResultData{ StudentInfo: convertCETStudentInfo(cetResult.StudentInfo), Scores: convertCETScores(cetResult.Scores), }, nil } func convertCETStudentInfo(info parser.CETStudentInfo) *pb.CetStudentInfo { return &pb.CetStudentInfo{ StudentId: info.StudentID, Name: info.Name, Gender: info.Gender, IdCard: info.IDCard, Duration: info.Duration, Grade: info.Grade, College: info.College, Major: info.Major, } } func convertCETScores(scores []parser.CETScore) []*pb.CetScore { result := make([]*pb.CetScore, 0, len(scores)) for _, score := range scores { result = append(result, &pb.CetScore{ Level: score.Level, ExamTime: score.ExamTime, TicketNum: score.TicketNum, Score: score.Score, }) } return result }