2026-03-13 20:43:44 +08:00
|
|
|
|
syntax = "proto3";
|
|
|
|
|
|
|
|
|
|
|
|
package runner;
|
|
|
|
|
|
|
2026-03-16 13:40:53 +08:00
|
|
|
|
option go_package = "schedule_converter/proto/runner;runner";
|
2026-03-13 20:43:44 +08:00
|
|
|
|
|
|
|
|
|
|
// ============================================================
|
|
|
|
|
|
// 服务定义
|
|
|
|
|
|
// ============================================================
|
|
|
|
|
|
|
|
|
|
|
|
// RunnerHub 服务 - 由 Backend 服务器实现
|
|
|
|
|
|
// Runner 作为客户端主动连接,建立双向流通信
|
|
|
|
|
|
service RunnerHub {
|
|
|
|
|
|
// Connect 建立双向流连接
|
|
|
|
|
|
// Runner 通过此连接注册、接收任务、返回结果
|
|
|
|
|
|
rpc Connect(stream StreamMessage) returns (stream StreamMessage);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ============================================================
|
|
|
|
|
|
// 流消息包装 - 所有消息通过 oneof 包装
|
|
|
|
|
|
// ============================================================
|
|
|
|
|
|
|
|
|
|
|
|
// StreamMessage 双向流消息包装
|
|
|
|
|
|
message StreamMessage {
|
|
|
|
|
|
oneof message {
|
|
|
|
|
|
RegisterRequest register = 1; // Runner 注册请求
|
|
|
|
|
|
RegisterResponse register_response = 2; // 注册响应
|
|
|
|
|
|
Heartbeat heartbeat = 3; // 心跳请求
|
|
|
|
|
|
HeartbeatAck heartbeat_ack = 4; // 心跳响应
|
|
|
|
|
|
Task task = 5; // 下发的任务
|
|
|
|
|
|
TaskResult result = 6; // 任务结果
|
|
|
|
|
|
TaskCancel task_cancel = 7; // 取消任务
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ============================================================
|
|
|
|
|
|
// 注册相关消息
|
|
|
|
|
|
// ============================================================
|
|
|
|
|
|
|
|
|
|
|
|
// RegisterRequest Runner 注册请求
|
|
|
|
|
|
message RegisterRequest {
|
|
|
|
|
|
string runner_id = 1; // Runner 唯一标识 (UUID)
|
|
|
|
|
|
string version = 2; // Runner 版本号
|
|
|
|
|
|
map<string, string> capabilities = 3; // 能力标签
|
|
|
|
|
|
// 例如: {"login": "true", "schedule": "true", "grades": "true"}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// RegisterResponse 注册响应
|
|
|
|
|
|
message RegisterResponse {
|
|
|
|
|
|
bool success = 1; // 是否成功
|
|
|
|
|
|
string session_id = 2; // 会话ID,用于标识本次连接
|
|
|
|
|
|
string message = 3; // 消息说明
|
|
|
|
|
|
int32 heartbeat_interval = 4; // 心跳间隔 (秒)
|
|
|
|
|
|
int32 task_timeout = 5; // 默认任务超时时间 (秒)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ============================================================
|
|
|
|
|
|
// 心跳消息
|
|
|
|
|
|
// ============================================================
|
|
|
|
|
|
|
|
|
|
|
|
// Heartbeat 心跳请求
|
|
|
|
|
|
message Heartbeat {
|
|
|
|
|
|
int64 timestamp = 1; // 客户端时间戳 (毫秒)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// HeartbeatAck 心跳响应
|
|
|
|
|
|
message HeartbeatAck {
|
|
|
|
|
|
int64 timestamp = 1; // 服务端时间戳 (毫秒)
|
|
|
|
|
|
int64 latency = 2; // 往返延迟 (毫秒)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ============================================================
|
|
|
|
|
|
// 任务定义
|
|
|
|
|
|
// ============================================================
|
|
|
|
|
|
|
|
|
|
|
|
// TaskType 任务类型枚举
|
|
|
|
|
|
enum TaskType {
|
|
|
|
|
|
TASK_TYPE_UNKNOWN = 0; // 未知类型
|
|
|
|
|
|
TASK_TYPE_LOGIN = 1; // 登录验证
|
|
|
|
|
|
TASK_TYPE_GET_SCHEDULE = 2; // 获取课表
|
|
|
|
|
|
TASK_TYPE_GET_GRADES = 3; // 获取成绩
|
|
|
|
|
|
TASK_TYPE_GET_EXAMS = 4; // 获取考试安排
|
|
|
|
|
|
TASK_TYPE_GET_USER_INFO = 5; // 获取用户信息
|
2026-06-02 13:59:30 +08:00
|
|
|
|
TASK_TYPE_GET_EMPTY_CLASSROOM = 6; // 获取空教室
|
2026-06-17 12:21:27 +08:00
|
|
|
|
TASK_TYPE_GET_CET = 7; // 获取四六级成绩
|
2026-03-13 20:43:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TaskStatus 任务状态枚举
|
|
|
|
|
|
enum TaskStatus {
|
|
|
|
|
|
TASK_STATUS_UNKNOWN = 0; // 未知状态
|
|
|
|
|
|
TASK_STATUS_SUCCESS = 1; // 成功
|
|
|
|
|
|
TASK_STATUS_FAILED = 2; // 失败
|
|
|
|
|
|
TASK_STATUS_TIMEOUT = 3; // 超时
|
|
|
|
|
|
TASK_STATUS_CANCELLED = 4; // 已取消
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Task 任务定义
|
|
|
|
|
|
message Task {
|
|
|
|
|
|
string task_id = 1; // 任务唯一ID (UUID)
|
|
|
|
|
|
TaskType type = 2; // 任务类型
|
|
|
|
|
|
int64 created_at = 3; // 创建时间戳 (毫秒)
|
|
|
|
|
|
int32 timeout_seconds = 4; // 超时时间 (秒)
|
|
|
|
|
|
bytes payload = 5; // 任务载荷 (JSON 编码)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TaskCancel 取消任务
|
|
|
|
|
|
message TaskCancel {
|
|
|
|
|
|
string task_id = 1; // 要取消的任务ID
|
|
|
|
|
|
string reason = 2; // 取消原因
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TaskResult 任务结果
|
|
|
|
|
|
message TaskResult {
|
|
|
|
|
|
string task_id = 1; // 任务ID
|
|
|
|
|
|
TaskStatus status = 2; // 执行状态
|
|
|
|
|
|
int64 completed_at = 3; // 完成时间戳 (毫秒)
|
|
|
|
|
|
bytes data = 4; // 结果数据 (JSON 编码)
|
|
|
|
|
|
string error_code = 5; // 错误码
|
|
|
|
|
|
string error_message = 6; // 错误消息
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ============================================================
|
|
|
|
|
|
// 任务载荷定义 - 用于 JSON 序列化到 bytes
|
|
|
|
|
|
// ============================================================
|
|
|
|
|
|
|
|
|
|
|
|
// LoginPayload 登录任务载荷
|
|
|
|
|
|
message LoginPayload {
|
|
|
|
|
|
string username = 1; // 学号
|
|
|
|
|
|
string password = 2; // 密码
|
|
|
|
|
|
string twfid = 3; // 初始 Cookie (可选)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// GetSchedulePayload 获取课表任务载荷
|
|
|
|
|
|
message GetSchedulePayload {
|
|
|
|
|
|
string username = 1; // 学号
|
|
|
|
|
|
string password = 2; // 密码
|
|
|
|
|
|
string semester = 3; // 学期,如 "2025-20262"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// GetGradesPayload 获取成绩任务载荷
|
|
|
|
|
|
message GetGradesPayload {
|
|
|
|
|
|
string username = 1; // 学号
|
|
|
|
|
|
string password = 2; // 密码
|
|
|
|
|
|
string semester = 3; // 学期 (可选,为空则获取全部)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// GetExamsPayload 获取考试安排任务载荷
|
|
|
|
|
|
message GetExamsPayload {
|
|
|
|
|
|
string username = 1; // 学号
|
|
|
|
|
|
string password = 2; // 密码
|
|
|
|
|
|
string semester = 3; // 学期
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ============================================================
|
|
|
|
|
|
// 结果数据定义 - 用于 JSON 序列化到 bytes
|
|
|
|
|
|
// ============================================================
|
|
|
|
|
|
|
|
|
|
|
|
// ScheduleResultData 课表结果数据
|
|
|
|
|
|
message ScheduleResultData {
|
|
|
|
|
|
string semester = 1; // 学期
|
|
|
|
|
|
string student_id = 2; // 学号
|
|
|
|
|
|
string student_name = 3; // 学生姓名
|
|
|
|
|
|
repeated Course courses = 4; // 课程列表
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Course 课程信息
|
|
|
|
|
|
message Course {
|
|
|
|
|
|
string code = 1; // 课程代码
|
|
|
|
|
|
string name = 2; // 课程名称
|
|
|
|
|
|
string teacher = 3; // 授课教师
|
|
|
|
|
|
string room = 4; // 教室
|
|
|
|
|
|
float credit = 5; // 学分
|
|
|
|
|
|
repeated ScheduleTime schedule = 6; // 上课时间安排
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ScheduleTime 上课时间安排
|
|
|
|
|
|
message ScheduleTime {
|
|
|
|
|
|
string day = 1; // 星期几,"0"-"6" 表示周日到周六
|
|
|
|
|
|
repeated int32 sections = 2; // 节次,如 [1, 2, 3]
|
|
|
|
|
|
repeated int32 weeks = 3; // 周次,如 [1, 2, 3, 4, 5]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-11 15:53:26 +08:00
|
|
|
|
// GpaSummary 学分绩汇总信息
|
|
|
|
|
|
message GpaSummary {
|
|
|
|
|
|
string average_gpa = 1; // 平均学分绩
|
|
|
|
|
|
string rank = 2; // 专业排名
|
|
|
|
|
|
string exam_total_gpa = 3; // 考试课学分绩
|
|
|
|
|
|
string exam_total_credits = 4; // 考试课学分数
|
|
|
|
|
|
string fail_credits = 5; // 考查课不及格学分
|
|
|
|
|
|
string semesters = 6; // 计算学期数
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-13 20:43:44 +08:00
|
|
|
|
// GradesResultData 成绩结果数据
|
|
|
|
|
|
message GradesResultData {
|
|
|
|
|
|
string semester = 1; // 学期
|
|
|
|
|
|
string student_id = 2; // 学号
|
|
|
|
|
|
repeated Grade grades = 3; // 成绩列表
|
2026-05-11 15:53:26 +08:00
|
|
|
|
GpaSummary gpa_summary = 4; // 学分绩汇总 (可选)
|
2026-03-13 20:43:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Grade 成绩信息
|
|
|
|
|
|
message Grade {
|
2026-05-11 15:53:26 +08:00
|
|
|
|
string term = 1; // 学期
|
|
|
|
|
|
string course_code = 2; // 课程代码
|
|
|
|
|
|
string course_name = 3; // 课程名称
|
|
|
|
|
|
string nature = 4; // 课程性质
|
|
|
|
|
|
string category = 5; // 课程类别
|
|
|
|
|
|
string credit = 6; // 学分
|
|
|
|
|
|
string score = 7; // 成绩 (可能是等级或分数)
|
|
|
|
|
|
string grade_point = 8; // 绩点
|
|
|
|
|
|
string is_exam = 9; // 是否考试课
|
2026-06-17 12:21:27 +08:00
|
|
|
|
bool is_retake = 10; // 是否为补考
|
2026-03-13 20:43:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ExamsResultData 考试安排结果数据
|
|
|
|
|
|
message ExamsResultData {
|
|
|
|
|
|
string semester = 1; // 学期
|
|
|
|
|
|
string student_id = 2; // 学号
|
|
|
|
|
|
repeated Exam exams = 3; // 考试列表
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Exam 考试信息
|
|
|
|
|
|
message Exam {
|
2026-05-11 15:53:26 +08:00
|
|
|
|
string course_name = 1; // 课程名称
|
|
|
|
|
|
string exam_type = 2; // 考试类型 (期末/期中/补考)
|
|
|
|
|
|
string date = 3; // 考试日期
|
|
|
|
|
|
string time = 4; // 考试时间
|
|
|
|
|
|
string week = 5; // 考试周次
|
|
|
|
|
|
string weekday = 6; // 星期几
|
2026-03-13 20:43:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// UserInfoResultData 用户信息结果数据
|
|
|
|
|
|
message UserInfoResultData {
|
|
|
|
|
|
string student_id = 1; // 学号
|
|
|
|
|
|
string name = 2; // 姓名
|
|
|
|
|
|
string gender = 3; // 性别
|
|
|
|
|
|
string college = 4; // 学院
|
|
|
|
|
|
string major = 5; // 专业
|
|
|
|
|
|
string class_name = 6; // 班级
|
|
|
|
|
|
string grade = 7; // 年级
|
|
|
|
|
|
}
|
2026-06-02 13:59:30 +08:00
|
|
|
|
|
|
|
|
|
|
// 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; // 周次范围
|
|
|
|
|
|
}
|
2026-06-17 12:21:27 +08:00
|
|
|
|
|
|
|
|
|
|
// GetCetPayload 获取四六级成绩任务载荷
|
|
|
|
|
|
message GetCetPayload {
|
|
|
|
|
|
string username = 1; // 学号
|
|
|
|
|
|
string password = 2; // 密码
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// CetScore 四六级成绩条目
|
|
|
|
|
|
message CetScore {
|
|
|
|
|
|
string level = 1; // 等级(英语四级/英语六级)
|
|
|
|
|
|
string exam_time = 2; // 考试时间,如 2025年06月
|
|
|
|
|
|
string ticket_num = 3; // 准考证号
|
|
|
|
|
|
string score = 4; // 成绩
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// CetStudentInfo 四六级查询页面的学生信息
|
|
|
|
|
|
message CetStudentInfo {
|
|
|
|
|
|
string student_id = 1; // 学号
|
|
|
|
|
|
string name = 2; // 姓名
|
|
|
|
|
|
string gender = 3; // 性别
|
|
|
|
|
|
string id_card = 4; // 身份证号
|
|
|
|
|
|
string duration = 5; // 学制
|
|
|
|
|
|
string grade = 6; // 年级
|
|
|
|
|
|
string college = 7; // 学院
|
|
|
|
|
|
string major = 8; // 专业
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// CetResultData 四六级成绩结果数据
|
|
|
|
|
|
message CetResultData {
|
|
|
|
|
|
CetStudentInfo student_info = 1; // 学生信息
|
|
|
|
|
|
repeated CetScore scores = 2; // 成绩列表
|
|
|
|
|
|
}
|