76 lines
1.9 KiB
Go
76 lines
1.9 KiB
Go
|
|
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
|
||
|
|
}
|