78 lines
2.5 KiB
Go
78 lines
2.5 KiB
Go
|
|
package service
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"context"
|
|||
|
|
"fmt"
|
|||
|
|
"log/slog"
|
|||
|
|
"net/http"
|
|||
|
|
"strings"
|
|||
|
|
|
|||
|
|
"schedule_converter/client"
|
|||
|
|
"schedule_converter/config"
|
|||
|
|
"schedule_converter/models"
|
|||
|
|
"schedule_converter/parser"
|
|||
|
|
apperr "schedule_converter/pkg/errors"
|
|||
|
|
|
|||
|
|
pb "schedule_converter/proto/runner"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// GetEmptyClassrooms 获取空教室:登录 → GET 建立会话 → POST 查询 → 解析 → 转换为 pb 结果。
|
|||
|
|
func (s *Service) GetEmptyClassrooms(ctx context.Context, req *pb.GetEmptyClassroomPayload) (*pb.EmptyClassroomResultData, 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
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
kjsURL := config.Get().BaseURL + "/kjscx/queryKjs"
|
|||
|
|
|
|||
|
|
// 先 GET 建立会话(沿用原有行为:直接用 client.Get,仅取 cookie,丢弃 body)。
|
|||
|
|
sessionReq, err := http.NewRequestWithContext(ctx, "GET", kjsURL, nil)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, apperr.New("session_classroom", err, "建立空教室会话失败")
|
|||
|
|
}
|
|||
|
|
sessionReq.Header = client.GetHeaders()
|
|||
|
|
sessionResp, err := httpClient.Do(sessionReq)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, apperr.New("session_classroom", err, "访问空教室页面失败")
|
|||
|
|
}
|
|||
|
|
sessionResp.Body.Close()
|
|||
|
|
|
|||
|
|
// POST 查询参数。
|
|||
|
|
data := fmt.Sprintf("pageXnxq=%s&pageZc1=%s&pageZc2=%s&pageXiaoqu=%s",
|
|||
|
|
req.Semester, req.WeekStart, req.WeekEnd, req.CampusCode)
|
|||
|
|
html, err := client.FetchHTML(ctx, httpClient, "POST", "/kjscx/queryKjs", strings.NewReader(data), "application/x-www-form-urlencoded", "/kjscx/queryKjs")
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, apperr.New("fetch_empty_classrooms", err, "查询空教室失败")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
entries, err := parser.ParseEmptyClassroomHTML(html, req.Semester, req.WeekStart, req.WeekEnd)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, apperr.New("parse_empty_classrooms", err, "解析空教室失败")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
log.Info("空教室获取成功", "classroom_count", len(entries))
|
|||
|
|
|
|||
|
|
return &pb.EmptyClassroomResultData{
|
|||
|
|
StudentId: req.Username,
|
|||
|
|
Semester: req.Semester,
|
|||
|
|
Classrooms: convertEmptyClassrooms(entries),
|
|||
|
|
}, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// convertEmptyClassrooms 将内部空教室模型转换为 pb.EmptyClassroomEntry 列表。
|
|||
|
|
func convertEmptyClassrooms(entries []models.EmptyClassroomEntry) []*pb.EmptyClassroomEntry {
|
|||
|
|
result := make([]*pb.EmptyClassroomEntry, 0, len(entries))
|
|||
|
|
for _, e := range entries {
|
|||
|
|
result = append(result, &pb.EmptyClassroomEntry{
|
|||
|
|
Classroom: e.Classroom,
|
|||
|
|
Weekday: e.Weekday,
|
|||
|
|
Periods: e.Periods,
|
|||
|
|
Term: e.Term,
|
|||
|
|
Weeks: e.Weeks,
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
return result
|
|||
|
|
}
|