feat(grpc): enhance grades and exams data structures
All checks were successful
Build / build (push) Successful in 1m39s

Update the gRPC service definitions and handlers to provide more detailed
information for grades and exams.

- Add `GpaSummary` message to include average GPA, rank, and other
  academic statistics.
- Expand `Grade` message with additional fields like `term`, `nature`,
  `category`, and `is_exam`.
- Refactor `Exam` message to use `week` and `weekday` instead of `room`
  and `seat`.
- Update `TaskHandler.getGrades` to populate the new `GpaSummary` and
  enriched grade details.
- Update protobuf generated files to reflect schema changes.
This commit is contained in:
2026-05-11 15:53:26 +08:00
parent 478ec3e3ab
commit d64f2fa20b
4 changed files with 276 additions and 137 deletions

View File

@@ -8,8 +8,6 @@ import (
"net/http"
"net/http/cookiejar"
"net/url"
"strconv"
"strings"
"sync"
"time"
@@ -247,21 +245,32 @@ func (h *TaskHandler) getGrades(ctx context.Context, payload []byte) ([]byte, er
return nil, err
}
_, grades, err := parser.FetchGPA(httpClient)
var gpaSummary *pb.GpaSummary
summary, grades, err := parser.FetchGPA(httpClient)
if err != nil {
log.Warn("获取GPA页面失败尝试成绩页面", "error", err)
grades, err = parser.FetchGrades(httpClient, parser.ScoreTypeFinal)
if err != nil {
return nil, apperr.New("fetch_grades", err, "获取成绩失败")
}
} else if summary != nil {
gpaSummary = &pb.GpaSummary{
AverageGpa: summary.AverageGPA,
Rank: summary.Rank,
ExamTotalGpa: summary.ExamTotalGPA,
ExamTotalCredits: summary.ExamTotalCredits,
FailCredits: summary.FailCredits,
Semesters: summary.Semesters,
}
}
pbGrades := convertGrades(grades)
result := &pb.GradesResultData{
StudentId: req.Username,
Semester: req.Semester,
Grades: pbGrades,
StudentId: req.Username,
Semester: req.Semester,
Grades: pbGrades,
GpaSummary: gpaSummary,
}
log.Info("成绩获取成功", "grade_count", len(pbGrades))
@@ -338,20 +347,16 @@ func convertToInt32(arr []int) []int32 {
func convertGrades(grades []parser.GradeEntry) []*pb.Grade {
result := make([]*pb.Grade, 0, len(grades))
for _, g := range grades {
var credit float32
if v, err := parseFloat(g.Credit); err == nil {
credit = v
}
var gradePoint float32
if v, err := parseFloat(g.GradePoint); err == nil {
gradePoint = v
}
result = append(result, &pb.Grade{
Term: g.Term,
CourseCode: g.Code,
CourseName: g.Name,
Credit: credit,
Grade: g.Score,
GradePoint: gradePoint,
Nature: g.Nature,
Category: g.Category,
Credit: g.Credit,
Score: g.Score,
GradePoint: g.GradePoint,
IsExam: g.IsExam,
})
}
return result
@@ -372,21 +377,9 @@ func convertExams(exams []parser.ExamEntry) []*pb.Exam {
ExamType: examTypeStr,
Date: e.Date,
Time: e.Time,
Room: e.Week,
Seat: e.Weekday,
Week: e.Week,
Weekday: e.Weekday,
})
}
return result
}
func parseFloat(s string) (float32, error) {
s = strings.TrimSpace(s)
if s == "" || s == "-" {
return 0, fmt.Errorf("empty")
}
v, err := strconv.ParseFloat(s, 32)
if err != nil {
return 0, err
}
return float32(v), nil
}