feat(grpc): add support for fetching empty classrooms
All checks were successful
Build / build (push) Successful in 1m31s
All checks were successful
Build / build (push) Successful in 1m31s
Implement the `TASK_TYPE_GET_EMPTY_CLASSROOM` task type to allow users to fetch available classroom information. - Add `TASK_TYPE_GET_EMPTY_CLASSROOM` to the `TaskType` enum in protobuf. - Define `GetEmptyClassroomPayload` and `EmptyClassroomResultData` messages. - Implement `getEmptyClassrooms`
This commit is contained in:
@@ -77,10 +77,11 @@ func (c *Client) register() error {
|
|||||||
RunnerId: c.runnerID,
|
RunnerId: c.runnerID,
|
||||||
Version: c.version,
|
Version: c.version,
|
||||||
Capabilities: map[string]string{
|
Capabilities: map[string]string{
|
||||||
"TASK_TYPE_GET_SCHEDULE": "true",
|
"TASK_TYPE_GET_SCHEDULE": "true",
|
||||||
"TASK_TYPE_GET_GRADES": "true",
|
"TASK_TYPE_GET_GRADES": "true",
|
||||||
"TASK_TYPE_GET_EXAMS": "true",
|
"TASK_TYPE_GET_EXAMS": "true",
|
||||||
"TASK_TYPE_LOGIN": "true",
|
"TASK_TYPE_LOGIN": "true",
|
||||||
|
"TASK_TYPE_GET_EMPTY_CLASSROOM": "true",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ func (h *TaskHandler) Execute(task *pb.Task) *pb.TaskResult {
|
|||||||
data, err = h.getExams(context.Background(), task.Payload)
|
data, err = h.getExams(context.Background(), task.Payload)
|
||||||
case pb.TaskType_TASK_TYPE_LOGIN:
|
case pb.TaskType_TASK_TYPE_LOGIN:
|
||||||
data, err = h.login(context.Background(), task.Payload)
|
data, err = h.login(context.Background(), task.Payload)
|
||||||
|
case pb.TaskType_TASK_TYPE_GET_EMPTY_CLASSROOM:
|
||||||
|
data, err = h.getEmptyClassrooms(context.Background(), task.Payload)
|
||||||
default:
|
default:
|
||||||
result.Status = pb.TaskStatus_TASK_STATUS_FAILED
|
result.Status = pb.TaskStatus_TASK_STATUS_FAILED
|
||||||
result.ErrorMessage = fmt.Sprintf("未知的任务类型: %v", task.Type)
|
result.ErrorMessage = fmt.Sprintf("未知的任务类型: %v", task.Type)
|
||||||
@@ -383,3 +385,55 @@ func convertExams(exams []parser.ExamEntry) []*pb.Exam {
|
|||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *TaskHandler) getEmptyClassrooms(ctx context.Context, payload []byte) ([]byte, error) {
|
||||||
|
var req pb.GetEmptyClassroomPayload
|
||||||
|
if err := json.Unmarshal(payload, &req); err != nil {
|
||||||
|
return nil, apperr.New("parse_payload", err, "解析任务载荷失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
log := slog.With("username", req.Username, "semester", req.Semester)
|
||||||
|
log.Info("获取空教室任务")
|
||||||
|
|
||||||
|
httpClient, err := createHTTPClient()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg := config.Get()
|
||||||
|
setTWFIDCookie(httpClient, cfg.BaseURL, "")
|
||||||
|
|
||||||
|
if err := executeLogin(ctx, httpClient, req.Username, req.Password); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
classrooms, err := parser.FetchEmptyClassrooms(httpClient, req.Semester, req.WeekStart, req.WeekEnd, req.CampusCode)
|
||||||
|
if err != nil {
|
||||||
|
return nil, apperr.New("fetch_empty_classrooms", err, "获取空教室失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
pbClassrooms := convertEmptyClassrooms(classrooms)
|
||||||
|
|
||||||
|
result := &pb.EmptyClassroomResultData{
|
||||||
|
StudentId: req.Username,
|
||||||
|
Semester: req.Semester,
|
||||||
|
Classrooms: pbClassrooms,
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("空教室获取成功", "classroom_count", len(pbClassrooms))
|
||||||
|
return json.Marshal(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertEmptyClassrooms(entries []parser.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
|
||||||
|
}
|
||||||
|
|||||||
256
parser/empty_classroom.go
Normal file
256
parser/empty_classroom.go
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
package parser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"schedule_converter/client"
|
||||||
|
"schedule_converter/config"
|
||||||
|
|
||||||
|
"github.com/PuerkitoBio/goquery"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EmptyClassroomEntry struct {
|
||||||
|
Classroom string `json:"classroom"`
|
||||||
|
Weekday string `json:"weekday"`
|
||||||
|
Periods string `json:"periods"`
|
||||||
|
Term string `json:"term"`
|
||||||
|
Weeks string `json:"weeks"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BuildingInfo struct {
|
||||||
|
DM string `json:"dm"`
|
||||||
|
MC string `json:"mc"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type VenueInfo struct {
|
||||||
|
DM string `json:"dm"`
|
||||||
|
MC string `json:"mc"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func FetchEmptyClassrooms(httpClient *http.Client, semester, weekStart, weekEnd, campusCode string) ([]EmptyClassroomEntry, error) {
|
||||||
|
url := config.BaseURL + "/kjscx/queryKjs"
|
||||||
|
fmt.Printf("[空教室] 正在获取空教室数据 (学期=%s, 周次=%s-%s)...\n", semester, weekStart, weekEnd)
|
||||||
|
|
||||||
|
// First GET to establish session
|
||||||
|
resp, err := httpClient.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("访问空教室页面失败: %w", err)
|
||||||
|
}
|
||||||
|
resp.Body.Close()
|
||||||
|
|
||||||
|
// POST with query parameters
|
||||||
|
data := fmt.Sprintf("pageXnxq=%s&pageZc1=%s&pageZc2=%s&pageXiaoqu=%s",
|
||||||
|
semester, weekStart, weekEnd, campusCode)
|
||||||
|
req, err := http.NewRequest("POST", url, strings.NewReader(data))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header = client.GetHeadersWithContentType("application/x-www-form-urlencoded")
|
||||||
|
req.Header.Set("Referer", url)
|
||||||
|
|
||||||
|
resp, err = httpClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("查询空教室失败: %w", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
html, err := decodeResponseBody(resp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
entries, err := ParseEmptyClassroomHTML(html, semester, weekStart, weekEnd)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("[空教室] 共获取 %d 条空教室记录\n", len(entries))
|
||||||
|
return entries, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseEmptyClassroomHTML(html, semester, weekStart, weekEnd string) ([]EmptyClassroomEntry, error) {
|
||||||
|
if html == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean nbsp entities
|
||||||
|
cleaned := strings.ReplaceAll(html, " ", "")
|
||||||
|
cleaned = strings.ReplaceAll(cleaned, "&", "&")
|
||||||
|
|
||||||
|
doc, err := goquery.NewDocumentFromReader(strings.NewReader(cleaned))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
dayNames := [7]string{"星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"}
|
||||||
|
periodLabels := [6]string{"1,2", "3,4", "5,6", "7,8", "9,10", "11,12"}
|
||||||
|
|
||||||
|
var classrooms []EmptyClassroomEntry
|
||||||
|
|
||||||
|
doc.Find("table").Each(func(_ int, table *goquery.Selection) {
|
||||||
|
rows := table.Find("tr")
|
||||||
|
if rows.Length() < 3 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this table has "星期一" in header
|
||||||
|
headerText := ""
|
||||||
|
table.Find("th").Each(func(_ int, th *goquery.Selection) {
|
||||||
|
headerText += th.Text()
|
||||||
|
})
|
||||||
|
if !strings.Contains(headerText, "星期一") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse period row (second row) to map column index to (day, period)
|
||||||
|
periodRow := rows.Eq(1)
|
||||||
|
periodCells := periodRow.Find("td")
|
||||||
|
periodCellTexts := make([]string, periodCells.Length())
|
||||||
|
periodCells.Each(func(i int, cell *goquery.Selection) {
|
||||||
|
periodCellTexts[i] = strings.TrimSpace(cell.Text())
|
||||||
|
})
|
||||||
|
|
||||||
|
colToDayPeriod := make(map[int][2]string)
|
||||||
|
colIdx := 1
|
||||||
|
for dayIdx := 0; dayIdx < 7; dayIdx++ {
|
||||||
|
for periodIdx := 0; periodIdx < 6; periodIdx++ {
|
||||||
|
var periodText string
|
||||||
|
if colIdx < len(periodCellTexts) {
|
||||||
|
periodText = periodCellTexts[colIdx]
|
||||||
|
} else {
|
||||||
|
periodText = periodLabels[periodIdx]
|
||||||
|
}
|
||||||
|
colToDayPeriod[colIdx] = [2]string{dayNames[dayIdx], periodText}
|
||||||
|
colIdx++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data rows start from row 2+
|
||||||
|
rows.FilterFunction(func(_ int, row *goquery.Selection) bool {
|
||||||
|
return row.Index() >= 2
|
||||||
|
}).Each(func(_ int, row *goquery.Selection) {
|
||||||
|
cells := row.Find("td")
|
||||||
|
if cells.Length() < 2 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
classroomName := strings.TrimSpace(cells.First().Text())
|
||||||
|
if classroomName == "" || len(classroomName) < 2 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var slots []string
|
||||||
|
var weekdays []string
|
||||||
|
weekdaySet := make(map[string]bool)
|
||||||
|
|
||||||
|
for colIdx := 1; colIdx < cells.Length(); colIdx++ {
|
||||||
|
cell := cells.Eq(colIdx)
|
||||||
|
// Check if cell has kjs_icon div (indicates occupied, not empty)
|
||||||
|
hasIcon := false
|
||||||
|
cell.Find("div").Each(func(_ int, div *goquery.Selection) {
|
||||||
|
if classAttr, exists := div.Attr("class"); exists && strings.Contains(classAttr, "kjs_icon") {
|
||||||
|
hasIcon = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if !hasIcon && colToDayPeriod[colIdx][0] != "" {
|
||||||
|
dayName := colToDayPeriod[colIdx][0]
|
||||||
|
periodText := colToDayPeriod[colIdx][1]
|
||||||
|
var slot string
|
||||||
|
if periodText != "" {
|
||||||
|
slot = fmt.Sprintf("%s 第%s节", dayName, periodText)
|
||||||
|
} else {
|
||||||
|
slot = dayName
|
||||||
|
}
|
||||||
|
slots = append(slots, slot)
|
||||||
|
if !weekdaySet[dayName] {
|
||||||
|
weekdaySet[dayName] = true
|
||||||
|
weekdays = append(weekdays, dayName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(slots) > 0 {
|
||||||
|
weekStr := ""
|
||||||
|
if weekStart != "" && weekEnd != "" {
|
||||||
|
weekStr = fmt.Sprintf("%s-%s周", weekStart, weekEnd)
|
||||||
|
}
|
||||||
|
entry := EmptyClassroomEntry{
|
||||||
|
Classroom: classroomName,
|
||||||
|
Weekday: strings.Join(weekdays, ", "),
|
||||||
|
Periods: strings.Join(slots, "\n"),
|
||||||
|
Term: semester,
|
||||||
|
Weeks: weekStr,
|
||||||
|
}
|
||||||
|
classrooms = append(classrooms, entry)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return classrooms, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FetchBuildings(httpClient *http.Client, campusCode string) ([]BuildingInfo, error) {
|
||||||
|
url := config.BaseURL + "/kjscx/queryJxlListBySjid"
|
||||||
|
fmt.Printf("[空教室] 正在获取楼号列表 (校区=%s)...\n", campusCode)
|
||||||
|
|
||||||
|
data := fmt.Sprintf("id=%s", campusCode)
|
||||||
|
req, err := http.NewRequest("POST", url, strings.NewReader(data))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header = client.GetHeadersWithContentType("application/x-www-form-urlencoded")
|
||||||
|
req.Header.Set("Referer", config.BaseURL+"/kjscx/queryKjs")
|
||||||
|
|
||||||
|
resp, err := httpClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("获取楼号列表失败: %w", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
return nil, fmt.Errorf("获取楼号列表失败, 状态码: %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
var buildings []BuildingInfo
|
||||||
|
if err := decodeJSONResponse(resp, &buildings); err != nil {
|
||||||
|
return nil, fmt.Errorf("解析楼号列表失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return buildings, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FetchVenues(httpClient *http.Client, buildingCode string) ([]VenueInfo, error) {
|
||||||
|
url := config.BaseURL + "/kjscx/queryJxcdListBySjid"
|
||||||
|
fmt.Printf("[空教室] 正在获取场地列表 (楼号=%s)...\n", buildingCode)
|
||||||
|
|
||||||
|
data := fmt.Sprintf("id=%s", buildingCode)
|
||||||
|
req, err := http.NewRequest("POST", url, strings.NewReader(data))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header = client.GetHeadersWithContentType("application/x-www-form-urlencoded")
|
||||||
|
req.Header.Set("Referer", config.BaseURL+"/kjscx/queryKjs")
|
||||||
|
|
||||||
|
resp, err := httpClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("获取场地列表失败: %w", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
return nil, fmt.Errorf("获取场地列表失败, 状态码: %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
var venues []VenueInfo
|
||||||
|
if err := decodeJSONResponse(resp, &venues); err != nil {
|
||||||
|
return nil, fmt.Errorf("解析场地列表失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return venues, nil
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package parser
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -72,3 +73,11 @@ func isValidUTF8(data []byte) bool {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func decodeJSONResponse(resp *http.Response, v any) error {
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return json.NewDecoder(bytes.NewReader(body)).Decode(v)
|
||||||
|
}
|
||||||
@@ -25,12 +25,13 @@ const (
|
|||||||
type TaskType int32
|
type TaskType int32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TaskType_TASK_TYPE_UNKNOWN TaskType = 0 // 未知类型
|
TaskType_TASK_TYPE_UNKNOWN TaskType = 0 // 未知类型
|
||||||
TaskType_TASK_TYPE_LOGIN TaskType = 1 // 登录验证
|
TaskType_TASK_TYPE_LOGIN TaskType = 1 // 登录验证
|
||||||
TaskType_TASK_TYPE_GET_SCHEDULE TaskType = 2 // 获取课表
|
TaskType_TASK_TYPE_GET_SCHEDULE TaskType = 2 // 获取课表
|
||||||
TaskType_TASK_TYPE_GET_GRADES TaskType = 3 // 获取成绩
|
TaskType_TASK_TYPE_GET_GRADES TaskType = 3 // 获取成绩
|
||||||
TaskType_TASK_TYPE_GET_EXAMS TaskType = 4 // 获取考试安排
|
TaskType_TASK_TYPE_GET_EXAMS TaskType = 4 // 获取考试安排
|
||||||
TaskType_TASK_TYPE_GET_USER_INFO TaskType = 5 // 获取用户信息
|
TaskType_TASK_TYPE_GET_USER_INFO TaskType = 5 // 获取用户信息
|
||||||
|
TaskType_TASK_TYPE_GET_EMPTY_CLASSROOM TaskType = 6 // 获取空教室
|
||||||
)
|
)
|
||||||
|
|
||||||
// Enum value maps for TaskType.
|
// Enum value maps for TaskType.
|
||||||
@@ -42,14 +43,16 @@ var (
|
|||||||
3: "TASK_TYPE_GET_GRADES",
|
3: "TASK_TYPE_GET_GRADES",
|
||||||
4: "TASK_TYPE_GET_EXAMS",
|
4: "TASK_TYPE_GET_EXAMS",
|
||||||
5: "TASK_TYPE_GET_USER_INFO",
|
5: "TASK_TYPE_GET_USER_INFO",
|
||||||
|
6: "TASK_TYPE_GET_EMPTY_CLASSROOM",
|
||||||
}
|
}
|
||||||
TaskType_value = map[string]int32{
|
TaskType_value = map[string]int32{
|
||||||
"TASK_TYPE_UNKNOWN": 0,
|
"TASK_TYPE_UNKNOWN": 0,
|
||||||
"TASK_TYPE_LOGIN": 1,
|
"TASK_TYPE_LOGIN": 1,
|
||||||
"TASK_TYPE_GET_SCHEDULE": 2,
|
"TASK_TYPE_GET_SCHEDULE": 2,
|
||||||
"TASK_TYPE_GET_GRADES": 3,
|
"TASK_TYPE_GET_GRADES": 3,
|
||||||
"TASK_TYPE_GET_EXAMS": 4,
|
"TASK_TYPE_GET_EXAMS": 4,
|
||||||
"TASK_TYPE_GET_USER_INFO": 5,
|
"TASK_TYPE_GET_USER_INFO": 5,
|
||||||
|
"TASK_TYPE_GET_EMPTY_CLASSROOM": 6,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1711,6 +1714,237 @@ func (x *UserInfoResultData) GetGrade() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetEmptyClassroomPayload 获取空教室任务载荷
|
||||||
|
type GetEmptyClassroomPayload struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` // 学号
|
||||||
|
Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` // 密码
|
||||||
|
Semester string `protobuf:"bytes,3,opt,name=semester,proto3" json:"semester,omitempty"` // 学期
|
||||||
|
WeekStart string `protobuf:"bytes,4,opt,name=week_start,json=weekStart,proto3" json:"week_start,omitempty"` // 起始周次
|
||||||
|
WeekEnd string `protobuf:"bytes,5,opt,name=week_end,json=weekEnd,proto3" json:"week_end,omitempty"` // 结束周次
|
||||||
|
CampusCode string `protobuf:"bytes,6,opt,name=campus_code,json=campusCode,proto3" json:"campus_code,omitempty"` // 校区代码
|
||||||
|
BuildingCode string `protobuf:"bytes,7,opt,name=building_code,json=buildingCode,proto3" json:"building_code,omitempty"` // 楼号代码(可选)
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetEmptyClassroomPayload) Reset() {
|
||||||
|
*x = GetEmptyClassroomPayload{}
|
||||||
|
mi := &file_proto_runner_runner_proto_msgTypes[21]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetEmptyClassroomPayload) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*GetEmptyClassroomPayload) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *GetEmptyClassroomPayload) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proto_runner_runner_proto_msgTypes[21]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use GetEmptyClassroomPayload.ProtoReflect.Descriptor instead.
|
||||||
|
func (*GetEmptyClassroomPayload) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proto_runner_runner_proto_rawDescGZIP(), []int{21}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetEmptyClassroomPayload) GetUsername() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Username
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetEmptyClassroomPayload) GetPassword() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Password
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetEmptyClassroomPayload) GetSemester() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Semester
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetEmptyClassroomPayload) GetWeekStart() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.WeekStart
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetEmptyClassroomPayload) GetWeekEnd() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.WeekEnd
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetEmptyClassroomPayload) GetCampusCode() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.CampusCode
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetEmptyClassroomPayload) GetBuildingCode() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.BuildingCode
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// EmptyClassroomResultData 空教室结果数据
|
||||||
|
type EmptyClassroomResultData struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Semester string `protobuf:"bytes,1,opt,name=semester,proto3" json:"semester,omitempty"` // 学期
|
||||||
|
StudentId string `protobuf:"bytes,2,opt,name=student_id,json=studentId,proto3" json:"student_id,omitempty"` // 学号
|
||||||
|
Classrooms []*EmptyClassroomEntry `protobuf:"bytes,3,rep,name=classrooms,proto3" json:"classrooms,omitempty"` // 空教室列表
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EmptyClassroomResultData) Reset() {
|
||||||
|
*x = EmptyClassroomResultData{}
|
||||||
|
mi := &file_proto_runner_runner_proto_msgTypes[22]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EmptyClassroomResultData) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*EmptyClassroomResultData) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *EmptyClassroomResultData) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proto_runner_runner_proto_msgTypes[22]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use EmptyClassroomResultData.ProtoReflect.Descriptor instead.
|
||||||
|
func (*EmptyClassroomResultData) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proto_runner_runner_proto_rawDescGZIP(), []int{22}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EmptyClassroomResultData) GetSemester() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Semester
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EmptyClassroomResultData) GetStudentId() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.StudentId
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EmptyClassroomResultData) GetClassrooms() []*EmptyClassroomEntry {
|
||||||
|
if x != nil {
|
||||||
|
return x.Classrooms
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EmptyClassroomEntry 空教室条目
|
||||||
|
type EmptyClassroomEntry struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Classroom string `protobuf:"bytes,1,opt,name=classroom,proto3" json:"classroom,omitempty"` // 教室名称
|
||||||
|
Weekday string `protobuf:"bytes,2,opt,name=weekday,proto3" json:"weekday,omitempty"` // 星期几
|
||||||
|
Periods string `protobuf:"bytes,3,opt,name=periods,proto3" json:"periods,omitempty"` // 可用节次
|
||||||
|
Term string `protobuf:"bytes,4,opt,name=term,proto3" json:"term,omitempty"` // 学期描述
|
||||||
|
Weeks string `protobuf:"bytes,5,opt,name=weeks,proto3" json:"weeks,omitempty"` // 周次范围
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EmptyClassroomEntry) Reset() {
|
||||||
|
*x = EmptyClassroomEntry{}
|
||||||
|
mi := &file_proto_runner_runner_proto_msgTypes[23]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EmptyClassroomEntry) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*EmptyClassroomEntry) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *EmptyClassroomEntry) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proto_runner_runner_proto_msgTypes[23]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use EmptyClassroomEntry.ProtoReflect.Descriptor instead.
|
||||||
|
func (*EmptyClassroomEntry) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proto_runner_runner_proto_rawDescGZIP(), []int{23}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EmptyClassroomEntry) GetClassroom() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Classroom
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EmptyClassroomEntry) GetWeekday() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Weekday
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EmptyClassroomEntry) GetPeriods() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Periods
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EmptyClassroomEntry) GetTerm() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Term
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EmptyClassroomEntry) GetWeeks() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Weeks
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
var File_proto_runner_runner_proto protoreflect.FileDescriptor
|
var File_proto_runner_runner_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
const file_proto_runner_runner_proto_rawDesc = "" +
|
const file_proto_runner_runner_proto_rawDesc = "" +
|
||||||
@@ -1849,14 +2083,38 @@ const file_proto_runner_runner_proto_rawDesc = "" +
|
|||||||
"\x05major\x18\x05 \x01(\tR\x05major\x12\x1d\n" +
|
"\x05major\x18\x05 \x01(\tR\x05major\x12\x1d\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"class_name\x18\x06 \x01(\tR\tclassName\x12\x14\n" +
|
"class_name\x18\x06 \x01(\tR\tclassName\x12\x14\n" +
|
||||||
"\x05grade\x18\a \x01(\tR\x05grade*\xa2\x01\n" +
|
"\x05grade\x18\a \x01(\tR\x05grade\"\xee\x01\n" +
|
||||||
|
"\x18GetEmptyClassroomPayload\x12\x1a\n" +
|
||||||
|
"\busername\x18\x01 \x01(\tR\busername\x12\x1a\n" +
|
||||||
|
"\bpassword\x18\x02 \x01(\tR\bpassword\x12\x1a\n" +
|
||||||
|
"\bsemester\x18\x03 \x01(\tR\bsemester\x12\x1d\n" +
|
||||||
|
"\n" +
|
||||||
|
"week_start\x18\x04 \x01(\tR\tweekStart\x12\x19\n" +
|
||||||
|
"\bweek_end\x18\x05 \x01(\tR\aweekEnd\x12\x1f\n" +
|
||||||
|
"\vcampus_code\x18\x06 \x01(\tR\n" +
|
||||||
|
"campusCode\x12#\n" +
|
||||||
|
"\rbuilding_code\x18\a \x01(\tR\fbuildingCode\"\x92\x01\n" +
|
||||||
|
"\x18EmptyClassroomResultData\x12\x1a\n" +
|
||||||
|
"\bsemester\x18\x01 \x01(\tR\bsemester\x12\x1d\n" +
|
||||||
|
"\n" +
|
||||||
|
"student_id\x18\x02 \x01(\tR\tstudentId\x12;\n" +
|
||||||
|
"\n" +
|
||||||
|
"classrooms\x18\x03 \x03(\v2\x1b.runner.EmptyClassroomEntryR\n" +
|
||||||
|
"classrooms\"\x91\x01\n" +
|
||||||
|
"\x13EmptyClassroomEntry\x12\x1c\n" +
|
||||||
|
"\tclassroom\x18\x01 \x01(\tR\tclassroom\x12\x18\n" +
|
||||||
|
"\aweekday\x18\x02 \x01(\tR\aweekday\x12\x18\n" +
|
||||||
|
"\aperiods\x18\x03 \x01(\tR\aperiods\x12\x12\n" +
|
||||||
|
"\x04term\x18\x04 \x01(\tR\x04term\x12\x14\n" +
|
||||||
|
"\x05weeks\x18\x05 \x01(\tR\x05weeks*\xc5\x01\n" +
|
||||||
"\bTaskType\x12\x15\n" +
|
"\bTaskType\x12\x15\n" +
|
||||||
"\x11TASK_TYPE_UNKNOWN\x10\x00\x12\x13\n" +
|
"\x11TASK_TYPE_UNKNOWN\x10\x00\x12\x13\n" +
|
||||||
"\x0fTASK_TYPE_LOGIN\x10\x01\x12\x1a\n" +
|
"\x0fTASK_TYPE_LOGIN\x10\x01\x12\x1a\n" +
|
||||||
"\x16TASK_TYPE_GET_SCHEDULE\x10\x02\x12\x18\n" +
|
"\x16TASK_TYPE_GET_SCHEDULE\x10\x02\x12\x18\n" +
|
||||||
"\x14TASK_TYPE_GET_GRADES\x10\x03\x12\x17\n" +
|
"\x14TASK_TYPE_GET_GRADES\x10\x03\x12\x17\n" +
|
||||||
"\x13TASK_TYPE_GET_EXAMS\x10\x04\x12\x1b\n" +
|
"\x13TASK_TYPE_GET_EXAMS\x10\x04\x12\x1b\n" +
|
||||||
"\x17TASK_TYPE_GET_USER_INFO\x10\x05*\x8a\x01\n" +
|
"\x17TASK_TYPE_GET_USER_INFO\x10\x05\x12!\n" +
|
||||||
|
"\x1dTASK_TYPE_GET_EMPTY_CLASSROOM\x10\x06*\x8a\x01\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"TaskStatus\x12\x17\n" +
|
"TaskStatus\x12\x17\n" +
|
||||||
"\x13TASK_STATUS_UNKNOWN\x10\x00\x12\x17\n" +
|
"\x13TASK_STATUS_UNKNOWN\x10\x00\x12\x17\n" +
|
||||||
@@ -1880,32 +2138,35 @@ func file_proto_runner_runner_proto_rawDescGZIP() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var file_proto_runner_runner_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
var file_proto_runner_runner_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
||||||
var file_proto_runner_runner_proto_msgTypes = make([]protoimpl.MessageInfo, 22)
|
var file_proto_runner_runner_proto_msgTypes = make([]protoimpl.MessageInfo, 25)
|
||||||
var file_proto_runner_runner_proto_goTypes = []any{
|
var file_proto_runner_runner_proto_goTypes = []any{
|
||||||
(TaskType)(0), // 0: runner.TaskType
|
(TaskType)(0), // 0: runner.TaskType
|
||||||
(TaskStatus)(0), // 1: runner.TaskStatus
|
(TaskStatus)(0), // 1: runner.TaskStatus
|
||||||
(*StreamMessage)(nil), // 2: runner.StreamMessage
|
(*StreamMessage)(nil), // 2: runner.StreamMessage
|
||||||
(*RegisterRequest)(nil), // 3: runner.RegisterRequest
|
(*RegisterRequest)(nil), // 3: runner.RegisterRequest
|
||||||
(*RegisterResponse)(nil), // 4: runner.RegisterResponse
|
(*RegisterResponse)(nil), // 4: runner.RegisterResponse
|
||||||
(*Heartbeat)(nil), // 5: runner.Heartbeat
|
(*Heartbeat)(nil), // 5: runner.Heartbeat
|
||||||
(*HeartbeatAck)(nil), // 6: runner.HeartbeatAck
|
(*HeartbeatAck)(nil), // 6: runner.HeartbeatAck
|
||||||
(*Task)(nil), // 7: runner.Task
|
(*Task)(nil), // 7: runner.Task
|
||||||
(*TaskCancel)(nil), // 8: runner.TaskCancel
|
(*TaskCancel)(nil), // 8: runner.TaskCancel
|
||||||
(*TaskResult)(nil), // 9: runner.TaskResult
|
(*TaskResult)(nil), // 9: runner.TaskResult
|
||||||
(*LoginPayload)(nil), // 10: runner.LoginPayload
|
(*LoginPayload)(nil), // 10: runner.LoginPayload
|
||||||
(*GetSchedulePayload)(nil), // 11: runner.GetSchedulePayload
|
(*GetSchedulePayload)(nil), // 11: runner.GetSchedulePayload
|
||||||
(*GetGradesPayload)(nil), // 12: runner.GetGradesPayload
|
(*GetGradesPayload)(nil), // 12: runner.GetGradesPayload
|
||||||
(*GetExamsPayload)(nil), // 13: runner.GetExamsPayload
|
(*GetExamsPayload)(nil), // 13: runner.GetExamsPayload
|
||||||
(*ScheduleResultData)(nil), // 14: runner.ScheduleResultData
|
(*ScheduleResultData)(nil), // 14: runner.ScheduleResultData
|
||||||
(*Course)(nil), // 15: runner.Course
|
(*Course)(nil), // 15: runner.Course
|
||||||
(*ScheduleTime)(nil), // 16: runner.ScheduleTime
|
(*ScheduleTime)(nil), // 16: runner.ScheduleTime
|
||||||
(*GpaSummary)(nil), // 17: runner.GpaSummary
|
(*GpaSummary)(nil), // 17: runner.GpaSummary
|
||||||
(*GradesResultData)(nil), // 18: runner.GradesResultData
|
(*GradesResultData)(nil), // 18: runner.GradesResultData
|
||||||
(*Grade)(nil), // 19: runner.Grade
|
(*Grade)(nil), // 19: runner.Grade
|
||||||
(*ExamsResultData)(nil), // 20: runner.ExamsResultData
|
(*ExamsResultData)(nil), // 20: runner.ExamsResultData
|
||||||
(*Exam)(nil), // 21: runner.Exam
|
(*Exam)(nil), // 21: runner.Exam
|
||||||
(*UserInfoResultData)(nil), // 22: runner.UserInfoResultData
|
(*UserInfoResultData)(nil), // 22: runner.UserInfoResultData
|
||||||
nil, // 23: runner.RegisterRequest.CapabilitiesEntry
|
(*GetEmptyClassroomPayload)(nil), // 23: runner.GetEmptyClassroomPayload
|
||||||
|
(*EmptyClassroomResultData)(nil), // 24: runner.EmptyClassroomResultData
|
||||||
|
(*EmptyClassroomEntry)(nil), // 25: runner.EmptyClassroomEntry
|
||||||
|
nil, // 26: runner.RegisterRequest.CapabilitiesEntry
|
||||||
}
|
}
|
||||||
var file_proto_runner_runner_proto_depIdxs = []int32{
|
var file_proto_runner_runner_proto_depIdxs = []int32{
|
||||||
3, // 0: runner.StreamMessage.register:type_name -> runner.RegisterRequest
|
3, // 0: runner.StreamMessage.register:type_name -> runner.RegisterRequest
|
||||||
@@ -1915,7 +2176,7 @@ var file_proto_runner_runner_proto_depIdxs = []int32{
|
|||||||
7, // 4: runner.StreamMessage.task:type_name -> runner.Task
|
7, // 4: runner.StreamMessage.task:type_name -> runner.Task
|
||||||
9, // 5: runner.StreamMessage.result:type_name -> runner.TaskResult
|
9, // 5: runner.StreamMessage.result:type_name -> runner.TaskResult
|
||||||
8, // 6: runner.StreamMessage.task_cancel:type_name -> runner.TaskCancel
|
8, // 6: runner.StreamMessage.task_cancel:type_name -> runner.TaskCancel
|
||||||
23, // 7: runner.RegisterRequest.capabilities:type_name -> runner.RegisterRequest.CapabilitiesEntry
|
26, // 7: runner.RegisterRequest.capabilities:type_name -> runner.RegisterRequest.CapabilitiesEntry
|
||||||
0, // 8: runner.Task.type:type_name -> runner.TaskType
|
0, // 8: runner.Task.type:type_name -> runner.TaskType
|
||||||
1, // 9: runner.TaskResult.status:type_name -> runner.TaskStatus
|
1, // 9: runner.TaskResult.status:type_name -> runner.TaskStatus
|
||||||
15, // 10: runner.ScheduleResultData.courses:type_name -> runner.Course
|
15, // 10: runner.ScheduleResultData.courses:type_name -> runner.Course
|
||||||
@@ -1923,13 +2184,14 @@ var file_proto_runner_runner_proto_depIdxs = []int32{
|
|||||||
19, // 12: runner.GradesResultData.grades:type_name -> runner.Grade
|
19, // 12: runner.GradesResultData.grades:type_name -> runner.Grade
|
||||||
17, // 13: runner.GradesResultData.gpa_summary:type_name -> runner.GpaSummary
|
17, // 13: runner.GradesResultData.gpa_summary:type_name -> runner.GpaSummary
|
||||||
21, // 14: runner.ExamsResultData.exams:type_name -> runner.Exam
|
21, // 14: runner.ExamsResultData.exams:type_name -> runner.Exam
|
||||||
2, // 15: runner.RunnerHub.Connect:input_type -> runner.StreamMessage
|
25, // 15: runner.EmptyClassroomResultData.classrooms:type_name -> runner.EmptyClassroomEntry
|
||||||
2, // 16: runner.RunnerHub.Connect:output_type -> runner.StreamMessage
|
2, // 16: runner.RunnerHub.Connect:input_type -> runner.StreamMessage
|
||||||
16, // [16:17] is the sub-list for method output_type
|
2, // 17: runner.RunnerHub.Connect:output_type -> runner.StreamMessage
|
||||||
15, // [15:16] is the sub-list for method input_type
|
17, // [17:18] is the sub-list for method output_type
|
||||||
15, // [15:15] is the sub-list for extension type_name
|
16, // [16:17] is the sub-list for method input_type
|
||||||
15, // [15:15] is the sub-list for extension extendee
|
16, // [16:16] is the sub-list for extension type_name
|
||||||
0, // [0:15] is the sub-list for field type_name
|
16, // [16:16] is the sub-list for extension extendee
|
||||||
|
0, // [0:16] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_proto_runner_runner_proto_init() }
|
func init() { file_proto_runner_runner_proto_init() }
|
||||||
@@ -1952,7 +2214,7 @@ func file_proto_runner_runner_proto_init() {
|
|||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_runner_runner_proto_rawDesc), len(file_proto_runner_runner_proto_rawDesc)),
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_runner_runner_proto_rawDesc), len(file_proto_runner_runner_proto_rawDesc)),
|
||||||
NumEnums: 2,
|
NumEnums: 2,
|
||||||
NumMessages: 22,
|
NumMessages: 25,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 1,
|
NumServices: 1,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ enum TaskType {
|
|||||||
TASK_TYPE_GET_GRADES = 3; // 获取成绩
|
TASK_TYPE_GET_GRADES = 3; // 获取成绩
|
||||||
TASK_TYPE_GET_EXAMS = 4; // 获取考试安排
|
TASK_TYPE_GET_EXAMS = 4; // 获取考试安排
|
||||||
TASK_TYPE_GET_USER_INFO = 5; // 获取用户信息
|
TASK_TYPE_GET_USER_INFO = 5; // 获取用户信息
|
||||||
|
TASK_TYPE_GET_EMPTY_CLASSROOM = 6; // 获取空教室
|
||||||
}
|
}
|
||||||
|
|
||||||
// TaskStatus 任务状态枚举
|
// TaskStatus 任务状态枚举
|
||||||
@@ -236,3 +237,30 @@ message UserInfoResultData {
|
|||||||
string class_name = 6; // 班级
|
string class_name = 6; // 班级
|
||||||
string grade = 7; // 年级
|
string grade = 7; // 年级
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetEmptyClassroomPayload 获取空教室任务载荷
|
||||||
|
message GetEmptyClassroomPayload {
|
||||||
|
string username = 1; // 学号
|
||||||
|
string password = 2; // 密码
|
||||||
|
string semester = 3; // 学期
|
||||||
|
string week_start = 4; // 起始周次
|
||||||
|
string week_end = 5; // 结束周次
|
||||||
|
string campus_code = 6; // 校区代码
|
||||||
|
string building_code = 7; // 楼号代码(可选)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EmptyClassroomResultData 空教室结果数据
|
||||||
|
message EmptyClassroomResultData {
|
||||||
|
string semester = 1; // 学期
|
||||||
|
string student_id = 2; // 学号
|
||||||
|
repeated EmptyClassroomEntry classrooms = 3; // 空教室列表
|
||||||
|
}
|
||||||
|
|
||||||
|
// EmptyClassroomEntry 空教室条目
|
||||||
|
message EmptyClassroomEntry {
|
||||||
|
string classroom = 1; // 教室名称
|
||||||
|
string weekday = 2; // 星期几
|
||||||
|
string periods = 3; // 可用节次
|
||||||
|
string term = 4; // 学期描述
|
||||||
|
string weeks = 5; // 周次范围
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// - protoc-gen-go-grpc v1.6.1
|
// - protoc-gen-go-grpc v1.6.2
|
||||||
// - protoc v7.34.1
|
// - protoc v7.34.1
|
||||||
// source: proto/runner/runner.proto
|
// source: proto/runner/runner.proto
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user