package service import ( "context" "fmt" "strings" "schedule_converter/client" "schedule_converter/config" "schedule_converter/models" "schedule_converter/parser" apperr "schedule_converter/pkg/errors" pb "schedule_converter/proto/runner" ) // GetSchedule 获取课表:登录 → POST 查询 → 解析 → 转换为 pb 结果。 func (s *Service) GetSchedule(ctx context.Context, req *pb.GetSchedulePayload) (*pb.ScheduleResultData, error) { httpClient, err := s.newAuthenticatedClient(ctx, req.Username, req.Password, "") if err != nil { return nil, err } semester := req.Semester if semester == "" { semester = config.Get().Semester } data := fmt.Sprintf("xnxq=%s", semester) html, err := client.FetchHTML(ctx, httpClient, "POST", "/kbcx/queryGrkb", strings.NewReader(data), "application/x-www-form-urlencoded", "") if err != nil { return nil, apperr.New("fetch_schedule", err, "获取课表失败") } courses, err := parser.ParseScheduleHTML(html) if err != nil { return nil, apperr.New("parse_schedule", err, "解析课表失败") } return &pb.ScheduleResultData{ StudentId: req.Username, Semester: semester, Courses: convertCourses(courses), }, nil } // convertCourses 将内部课程模型转换为 pb.Course 列表。 func convertCourses(courses []models.Course) []*pb.Course { result := make([]*pb.Course, len(courses)) for i, c := range courses { schedule := make([]*pb.ScheduleTime, len(c.Schedule)) for j, sc := range c.Schedule { schedule[j] = &pb.ScheduleTime{ Day: sc.Day, Sections: toInt32Slice(sc.Section), Weeks: toInt32Slice(sc.Weeks), } } result[i] = &pb.Course{ Name: c.Name, Teacher: c.Teacher, Room: c.Room, Schedule: schedule, } } return result } func toInt32Slice(arr []int) []int32 { result := make([]int32, len(arr)) for i, v := range arr { result[i] = int32(v) } return result }