-
Notifications
You must be signed in to change notification settings - Fork 5
Feat/pe calc #30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Feat/pe calc #30
Conversation
概览本次变更涉及教学和员工模块的API演进。教学模块重组了课程日程响应数据结构,将课程信息和学期开始时间戳一起封装。员工模块新增三个健身分数管理的RPC方法(创建、更新、删除),并完善了相应的协议定义和OpenAPI文档。 变更详情
代码审查工作量🎯 3 (中等复杂度) | ⏱️ ~25 分钟 诗歌
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
campusapis/teaching/v1/teaching.proto (1)
203-213: GetScheduleResponse 的 data 类型变更会破坏兼容性
data从repeated ScheduleResponseCourse变成ScheduleResponseData会导致旧客户端解析失败/数据错乱(proto 与 JSON 都变了)。建议保持旧字段并新增版本化字段或升级 API 版本,避免现有调用方被破坏。🔧 兼容性修复建议(示例)
message GetScheduleResponse { int32 error = 1; string msg = 2; - ScheduleResponseData data = 3; + // 兼容旧客户端 + repeated ScheduleResponseCourse data = 3 [deprecated = true]; + // 新版结构 + ScheduleResponseData data_v2 = 4; }
🤖 Fix all issues with AI agents
In `@campusapis/fitness/v1/fitness.proto`:
- Around line 23-31: The PATCH RPC UpdateFitnessScore currently takes scalar
fields that can't represent "not provided" and risks accidental zeroing; fix by
either changing rpc UpdateFitnessScore to use PUT with a full FitnessScore
payload, or (preferred) keep PATCH but modify UpdateFitnessScoreRequest to
include a google.protobuf.FieldMask update_mask plus a single FitnessScore score
(or make scalar fields explicitly optional), update the HTTP annotation
accordingly, and ensure server-side update logic respects update_mask; apply the
same FieldMask/optional approach to the other PATCH RPCs in this proto that
suffer the same issue.
- Around line 12-19: additional_bindings for StoreFitnessScore and
UpdateFitnessScore omit body mapping, causing POST/PATCH to /fitness/score to
treat the payload as query params; update the RPC options for both
StoreFitnessScore and UpdateFitnessScore to add body: "*" inside their
additional_bindings so the /fitness/score binding maps the request body
correctly (i.e., ensure each additional_bindings block for these RPCs includes
body: "*").
- Line 7: Update the protobuf go_package option to a full Go module import path
instead of the relative path currently set in the file (the line `option
go_package = "./campusapis/fitness/v1";`); replace it with your module's full
import path plus an optional alias (for example
`github.com/your_org/your_repo/campusapis/fitness/v1;fitnessv1pb`) so
protoc-gen-go can generate importable Go code and keep the format consistent
with other proto files.
In `@campusapis/teaching/v1/courses.go`:
- Around line 3-13: The ToGetScheduleResponse method currently hardcodes
SemesterStartTimestamp using schoolConst.SemesterStartTimestamp which breaks
queries for non-default terms; change the signature of
Courses.ToGetScheduleResponse (the method on type Courses) to accept a
semesterStartTimestamp parameter and set
ScheduleResponseData.SemesterStartTimestamp to that parameter instead of
schoolConst.SemesterStartTimestamp, and update callers to compute/lookup the
correct semester start timestamp based on the GetScheduleRequest (year/term) and
pass it into ToGetScheduleResponse so historical/future term queries return the
correct value.
In `@docs/swagger/campusapis/fitness/v1/fitness.swagger.json`:
- Around line 62-199: The Swagger shows POST/PATCH to /fitness/score being
rendered as query params because the proto RPCs StoreFitnessScore and
UpdateFitnessScore omitted body: "*" in their additional_bindings; update both
RPC options so each additional_bindings block for StoreFitnessScore and
UpdateFitnessScore includes body: "*" (matching the primary binding), then
regenerate the Swagger to ensure /fitness/score endpoints use request body
instead of query parameters.
🧹 Nitpick comments (1)
docs/swagger/campusapis/fitness/v1/fitness.swagger.json (1)
1-18: 请确认是否需要鉴权:Swagger 未声明安全定义当前 Swagger 2.0 未包含
securityDefinitions与全局/operationsecurity。如果接口需要认证,这会导致文档和生成客户端缺失鉴权配置。请确认安全需求并补齐对应定义(如 API key/Bearer)。Also applies to: 448-476
campusapis/fitness/v1/fitness.proto
Outdated
|
|
||
| import "google/api/annotations.proto"; | ||
|
|
||
| option go_package = "./campusapis/fitness/v1"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find all go_package declarations
rg -n 'option go_package'
# Check module path
if [ -f go.mod ]; then
echo "=== go.mod ==="
head -5 go.mod
fiRepository: hduhelp/api_open_sdk
Length of output: 184
🌐 Web query:
Go modules proto go_package relative path import valid
💡 Result:
Short answer: With Go modules you must use module-aware (fully qualified) Go import paths in proto go_package values or supply equivalent mappings to protoc. Relative import paths (./ or ../) in go_package are not valid in module mode.
Why and options:
- protoc-gen-go expects a Go import path (e.g. example.com/project/protos/foo) in option go_package; generated imports and output placement are computed from that. Using relative paths breaks module-mode imports. [1][2]
- Alternatives:
- Put a full module path in option go_package (recommended). [2]
- Pass M=<import_path> mappings to protoc (or use build tooling that does this). [2]
- Use --go_opt=paths=source_relative (or the newer module= prefix behaviors) to control output placement, but you still must provide import paths for cross-file imports; the module flag can help place generated files under a module prefix. [1][3]
References:
[1] Protobuf Go generated code guide — packages, go_package, paths/module flags.
[2] Discussion / Q&A: relative imports in protobuf + Go modules (StackOverflow + community guidance).
[3] protoc-gen-go / release notes and module/paths behavior.
🌐 Web query:
protobuf go_package option best practices Go modules
💡 Result:
Short best-practices for option go_package when using Go modules
-
Always declare go_package inside the .proto. Use the full Go module import path (module path + package directory) so generated code has a stable import path. Example:
option go_package = "github.com/acme/project/api/proto/v1;apipb". [1][3] -
Include an explicit package name after a semicolon when the directory tail is not the desired Go package identifier:
option go_package = "github.com/acme/project/api/proto/v1;apipb". [1][3] -
Version your proto package paths for breaking changes (v1, v2…) consistent with Go module semantics (so import paths remain unique). [1][5]
-
Prefer a central module that publishes generated Go packages for widely‑shared protos rather than generating copies in many modules. This avoids duplicate protobuf descriptors and runtime global-registry conflicts. If you must generate in-repo, keep generated Go code in an internal/ package or a clearly isolated module. [1][2][5]
-
If you cannot edit upstream .proto files, map proto→Go import paths at generation time with protoc’s M flag (e.g. --go_opt=Mpath/to.proto=github.com/you/module/apipb). Prefer adding go_package upstream when possible. [1][4]
-
Pick unique proto package names (proto package and go package) — avoid generic names to prevent name collisions across repos. Coordinate with proto owners for a canonical go_package if the proto is shared. [1][2]
-
Don’t rely on implicit filesystem layout or GOPATH heuristics; be explicit in the .proto or with --go_opt mappings so builds are reproducible across modules/CI. [1][3]
Sources
- Official protobuf Go generated code guidance. [1]
- protobuf Go FAQ (vendoring, package conflicts). [2]
- Protobuf getting-started/Tutorial (examples of go_package usage). [3]
- StackOverflow discussion on generation with Go modules and go_package mappings. [4]
- Blog/discussion on storing/generated Go bindings and global registry issues. [5]
go_package 相对路径在 Go modules 中无效,需修改为完整 import path
option go_package = "./campusapis/fitness/v1"; 中的相对路径不符合 Go modules 规范。protoc-gen-go 要求 go_package 使用完整的 Go import path(例如 github.com/hduhelp/api_open_sdk/campusapis/fitness/v1),相对路径会导致生成的代码无法正常导入和使用。
建议改为完整 module path + 可选别名的形式,如 module/path/fitness/v1;fitnessv1pb,并与仓库其他 proto 文件保持一致。
🤖 Prompt for AI Agents
In `@campusapis/fitness/v1/fitness.proto` at line 7, Update the protobuf
go_package option to a full Go module import path instead of the relative path
currently set in the file (the line `option go_package =
"./campusapis/fitness/v1";`); replace it with your module's full import path
plus an optional alias (for example
`github.com/your_org/your_repo/campusapis/fitness/v1;fitnessv1pb`) so
protoc-gen-go can generate importable Go code and keep the format consistent
with other proto files.
campusapis/fitness/v1/fitness.proto
Outdated
| rpc StoreFitnessScore(StoreFitnessScoreRequest) returns (StoreFitnessScoreResponse) { | ||
| option (google.api.http) = { | ||
| post: "/fitness/v1/score" | ||
| body: "*" | ||
| additional_bindings { | ||
| post: "/fitness/score" | ||
| } | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
find . -name "fitness.proto" -type fRepository: hduhelp/api_open_sdk
Length of output: 101
🏁 Script executed:
cat -n ./campusapis/fitness/v1/fitness.protoRepository: hduhelp/api_open_sdk
Length of output: 3889
additional_bindings 缺少 body 导致请求体映射错误
StoreFitnessScore 和 UpdateFitnessScore 的 additional_bindings 均未声明 body: "*",导致 /fitness/score 的 POST/PATCH 请求参数被误解析为查询参数,与 /fitness/v1/score 行为不一致。需在两个 RPC 的 additional_bindings 中显式添加 body: "*":
建议修复
rpc StoreFitnessScore(StoreFitnessScoreRequest) returns (StoreFitnessScoreResponse) {
option (google.api.http) = {
post: "/fitness/v1/score"
body: "*"
additional_bindings {
post: "/fitness/score"
+ body: "*"
}
};
}
rpc UpdateFitnessScore(UpdateFitnessScoreRequest) returns (UpdateFitnessScoreResponse) {
option (google.api.http) = {
patch: "/fitness/v1/score"
body: "*"
additional_bindings {
patch: "/fitness/score"
+ body: "*"
}
};
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| rpc StoreFitnessScore(StoreFitnessScoreRequest) returns (StoreFitnessScoreResponse) { | |
| option (google.api.http) = { | |
| post: "/fitness/v1/score" | |
| body: "*" | |
| additional_bindings { | |
| post: "/fitness/score" | |
| } | |
| }; | |
| rpc StoreFitnessScore(StoreFitnessScoreRequest) returns (StoreFitnessScoreResponse) { | |
| option (google.api.http) = { | |
| post: "/fitness/v1/score" | |
| body: "*" | |
| additional_bindings { | |
| post: "/fitness/score" | |
| body: "*" | |
| } | |
| }; |
🤖 Prompt for AI Agents
In `@campusapis/fitness/v1/fitness.proto` around lines 12 - 19,
additional_bindings for StoreFitnessScore and UpdateFitnessScore omit body
mapping, causing POST/PATCH to /fitness/score to treat the payload as query
params; update the RPC options for both StoreFitnessScore and UpdateFitnessScore
to add body: "*" inside their additional_bindings so the /fitness/score binding
maps the request body correctly (i.e., ensure each additional_bindings block for
these RPCs includes body: "*").
campusapis/fitness/v1/fitness.proto
Outdated
| rpc UpdateFitnessScore(UpdateFitnessScoreRequest) returns (UpdateFitnessScoreResponse) { | ||
| option (google.api.http) = { | ||
| patch: "/fitness/v1/score" | ||
| body: "*" | ||
| additional_bindings { | ||
| patch: "/fitness/score" | ||
| } | ||
| }; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PATCH 请求缺少字段 presence,无法安全做部分更新
UpdateFitnessScoreRequest 的字段全为标量且不可区分“未提供”与“零值”,但你们用的是 PATCH。若客户端只传部分字段,将无法避免“误清零”。建议:
- 改为 PUT(要求完整 payload),或
- 引入
google.protobuf.FieldMask+FitnessScore/optional字段来表达更新范围。
Also applies to: 72-91
🤖 Prompt for AI Agents
In `@campusapis/fitness/v1/fitness.proto` around lines 23 - 31, The PATCH RPC
UpdateFitnessScore currently takes scalar fields that can't represent "not
provided" and risks accidental zeroing; fix by either changing rpc
UpdateFitnessScore to use PUT with a full FitnessScore payload, or (preferred)
keep PATCH but modify UpdateFitnessScoreRequest to include a
google.protobuf.FieldMask update_mask plus a single FitnessScore score (or make
scalar fields explicitly optional), update the HTTP annotation accordingly, and
ensure server-side update logic respects update_mask; apply the same
FieldMask/optional approach to the other PATCH RPCs in this proto that suffer
the same issue.
| import ( | ||
| "github.com/hduhelp/api_open_sdk/campusapis/staff" | ||
| "github.com/hduhelp/api_open_sdk/schoolConst" | ||
| ) | ||
|
|
||
| func (x *Courses) ToGetScheduleResponse() *GetScheduleResponse { | ||
| return &GetScheduleResponse{ | ||
| Data: x.GetScheduleResponseCourse(), | ||
| Data: &ScheduleResponseData{ | ||
| Course: x.GetScheduleResponseCourse(), | ||
| SemesterStartTimestamp: schoolConst.SemesterStartTimestamp, | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❓ Verification inconclusive
Script executed:
find . -type f -name "courses.go" | grep -E "teaching/v1|campusapis" | head -5Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
./campusapis/teaching/v1/courses.go
Script executed:
git ls-files | grep -E "courses\.go|schoolConst" | head -20Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
campusapis/teaching/v1/courses.go
schoolConst/const.go
Script executed:
find . -type f -name "*.go" | grep -v vendor | head -30Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
./aggregatingapis/infostream/v1/infostream.pb.go
./aggregatingapis/infostream/v1/infostream.pb.gw.go
./aggregatingapis/infostream/v1/infostream_grpc.pb.go
./aggregatingapis/time/v1/time.pb.go
./aggregatingapis/time/v1/time.pb.gw.go
./aggregatingapis/time/v1/time_grpc.pb.go
./aliyun/sls/config.go
./aliyun/sls/sls.go
./api/cache/gocache.go
./api/cache/gocache_test.go
./api/cache/interface.go
./api/grpc_client/client.go
./api/grpc_gateway/grpc_gateway.go
./api/grpc_gateway/mux.go
./api/grpc_server/options.go
./api/grpc_server/server.go
./api/locker/locker.go
./api/locker/options.go
./api/locker/ratelimit.go
./campusapis/backup/backup.pb.go
./campusapis/backup/backup.pb.gw.go
./campusapis/backup/backup_grpc.pb.go
./campusapis/card/v1/card.pb.go
./campusapis/card/v1/card.pb.gw.go
./campusapis/card/v1/card_grpc.pb.go
./campusapis/gate/v1/callback.pb.go
./campusapis/gate/v1/callback.pb.gw.go
./campusapis/gate/v1/callback_grpc.pb.go
./campusapis/gate/v1/defined.go
./campusapis/gate/v1/defined.pb.go
Script executed:
cat -n ./campusapis/teaching/v1/courses.go | head -50Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
1 package teachingv1
2
3 import (
4 "github.com/hduhelp/api_open_sdk/campusapis/staff"
5 "github.com/hduhelp/api_open_sdk/schoolConst"
6 )
7
8 func (x *Courses) ToGetScheduleResponse() *GetScheduleResponse {
9 return &GetScheduleResponse{
10 Data: &ScheduleResponseData{
11 Course: x.GetScheduleResponseCourse(),
12 SemesterStartTimestamp: schoolConst.SemesterStartTimestamp,
13 },
14 }
15 }
16
17 func (x *Courses) GetScheduleResponseCourse() (list []*ScheduleResponseCourse) {
18 list = make([]*ScheduleResponseCourse, 0)
19 for _, v := range x.Items {
20 list = append(list, v.ToScheduleResponseCourse())
21 }
22 return list
23 }
24
25 func (i CourseItems) ToGetScheduleResponse() (list []*ScheduleResponseCourse) {
26 list = make([]*ScheduleResponseCourse, 0)
27 for _, v := range i {
28 list = append(list, v.ToScheduleResponseCourse())
29 }
30 return list
31 }
32
33 func (x *CourseItem) ToScheduleResponseCourse() *ScheduleResponseCourse {
34 return &ScheduleResponseCourse{
35 ClassID: x.ClassID,
36 ClassName: x.ClassName,
37 ClassTime: x.ClassTime,
38 CourseID: x.CourseID,
39 CourseName: x.CourseName,
40 Credit: x.Credit,
41 Schedule: x.GetScheduleResponseCourse_Schedule(),
42 SchoolYear: x.SchoolYear.FullName(),
43 Semester: x.Semester.Num,
44 }
45 }
46
47 func (x *CourseItem) GetScheduleResponseCourse_Schedule() (list []*ScheduleResponseCourse_ScheduleInfo) {
48 list = make([]*ScheduleResponseCourse_ScheduleInfo, 0)
49 if x.Schedule == nil {
50 return list
Script executed:
cat -n ./schoolConst/const.go | head -100Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
1 package schoolConst
2
3 import (
4 "math"
5 "time"
6 )
7
8 const (
9 SchoolYear = 2025
10 Semester = 1
11 SemesterStartTimestamp = int64(1757865600) // 2025-9-15 00:00:00
12 )
13
14 func getWeekNum() int {
15 timeStart := SemesterStartTimestamp
16 return int(math.Floor(float64(time.Now().Unix()-timeStart)/(86400*7))) + 1
17 }
18
19 func getWeekDay() int {
20 day := int(time.Now().Weekday())
21 return day
22 }
23
24 type TimeData struct {
25 SchoolYear int `json:"schoolYear"`
26 Semester int `json:"semester"`
27 SemesterStartTimestamp int64 `json:"semester_start_timestamp"`
28 WeekNow int `json:"weekNow"`
29 WeekDayNow int `json:"weekDayNow"`
30 Timestamp int64 `json:"timeStamp"`
31 Section int `json:"section"`
32 }
33
34 func GetTimeData() *TimeData {
35 timeNow := time.Now()
36 hour := timeNow.Hour()
37 minute := time.Now().Minute() + hour*60
38 tMap := []int{0, 530, 580, 645, 695, 745, 855, 905, 960, 1010, 1155, 1205, 1255}
39 section := -1
40 for i := 0; i < len(tMap); i++ {
41 if minute < tMap[i] {
42 section = i
43 break
44 }
45 }
46
47 timed := &TimeData{
48 SchoolYear: SchoolYear,
49 Semester: Semester,
50 SemesterStartTimestamp: SemesterStartTimestamp,
51 WeekNow: getWeekNum(),
52 WeekDayNow: getWeekDay(),
53 Timestamp: time.Now().Unix(),
54 Section: section,
55 }
56
57 return timed
58 }
Script executed:
rg "GetScheduleRequest" --type go | head -20Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
campusapis/teaching/v1/teaching_grpc.pb.go: GetSchedule(ctx context.Context, in *GetScheduleRequest, opts ...grpc.CallOption) (*GetScheduleResponse, error)
campusapis/teaching/v1/teaching_grpc.pb.go:func (c *teachingServiceClient) GetSchedule(ctx context.Context, in *GetScheduleRequest, opts ...grpc.CallOption) (*GetScheduleResponse, error) {
campusapis/teaching/v1/teaching_grpc.pb.go: GetSchedule(context.Context, *GetScheduleRequest) (*GetScheduleResponse, error)
campusapis/teaching/v1/teaching_grpc.pb.go:func (UnimplementedTeachingServiceServer) GetSchedule(context.Context, *GetScheduleRequest) (*GetScheduleResponse, error) {
campusapis/teaching/v1/teaching_grpc.pb.go: in := new(GetScheduleRequest)
campusapis/teaching/v1/teaching_grpc.pb.go: return srv.(TeachingServiceServer).GetSchedule(ctx, req.(*GetScheduleRequest))
campusapis/teaching/v1/teaching.pb.gw.go: protoReq GetScheduleRequest
campusapis/teaching/v1/teaching.pb.gw.go: protoReq GetScheduleRequest
campusapis/teaching/v1/teaching.pb.gw.go: protoReq GetScheduleRequest
campusapis/teaching/v1/teaching.pb.gw.go: protoReq GetScheduleRequest
campusapis/teaching/v1/teaching.pb.gw.go: protoReq GetScheduleRequest
campusapis/teaching/v1/teaching.pb.gw.go: protoReq GetScheduleRequest
campusapis/teaching/v1/teaching.pb.go:// GetScheduleRequest 根据参数和预设优先级拼装查询日期
campusapis/teaching/v1/teaching.pb.go:type GetScheduleRequest struct {
campusapis/teaching/v1/teaching.pb.go:func (x *GetScheduleRequest) Reset() {
campusapis/teaching/v1/teaching.pb.go: *x = GetScheduleRequest{}
campusapis/teaching/v1/teaching.pb.go:func (x *GetScheduleRequest) String() string {
campusapis/teaching/v1/teaching.pb.go:func (*GetScheduleRequest) ProtoMessage() {}
campusapis/teaching/v1/teaching.pb.go:func (x *GetScheduleRequest) ProtoReflect() protoreflect.Message {
campusapis/teaching/v1/teaching.pb.go:// Deprecated: Use GetScheduleRequest.ProtoReflect.Descriptor instead.
Script executed:
rg "ToGetScheduleResponse" --type go -B 2 -A 2 | head -40Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
campusapis/teaching/v1/courses.go-)
campusapis/teaching/v1/courses.go-
campusapis/teaching/v1/courses.go:func (x *Courses) ToGetScheduleResponse() *GetScheduleResponse {
campusapis/teaching/v1/courses.go- return &GetScheduleResponse{
campusapis/teaching/v1/courses.go- Data: &ScheduleResponseData{
--
campusapis/teaching/v1/courses.go-}
campusapis/teaching/v1/courses.go-
campusapis/teaching/v1/courses.go:func (i CourseItems) ToGetScheduleResponse() (list []*ScheduleResponseCourse) {
campusapis/teaching/v1/courses.go- list = make([]*ScheduleResponseCourse, 0)
campusapis/teaching/v1/courses.go- for _, v := range i {
Script executed:
rg "SchoolYear\|Semester" --type go | grep -E "\.SchoolYear|\.Semester|x\." | head -30Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
Script executed:
rg "type GetScheduleRequest struct" --type go -A 15Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
campusapis/teaching/v1/teaching.pb.go:type GetScheduleRequest struct {
campusapis/teaching/v1/teaching.pb.go- state protoimpl.MessageState `protogen:"open.v1"`
campusapis/teaching/v1/teaching.pb.go- // 学期
campusapis/teaching/v1/teaching.pb.go- Semester string `protobuf:"bytes,1,opt,name=semester,proto3" json:"semester,omitempty"`
campusapis/teaching/v1/teaching.pb.go- // 学年 支持多种格式 如:2019-2020 2019
campusapis/teaching/v1/teaching.pb.go- SchoolYear string `protobuf:"bytes,2,opt,name=schoolYear,proto3" json:"schoolYear,omitempty"`
campusapis/teaching/v1/teaching.pb.go- // 时间戳
campusapis/teaching/v1/teaching.pb.go- Timestamp int32 `protobuf:"varint,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
campusapis/teaching/v1/teaching.pb.go- // 周次
campusapis/teaching/v1/teaching.pb.go- Week int32 `protobuf:"varint,4,opt,name=week,proto3" json:"week,omitempty"`
campusapis/teaching/v1/teaching.pb.go- // 星期几
campusapis/teaching/v1/teaching.pb.go- Weekday int32 `protobuf:"varint,5,opt,name=weekday,proto3" json:"weekday,omitempty"`
campusapis/teaching/v1/teaching.pb.go- unknownFields protoimpl.UnknownFields
campusapis/teaching/v1/teaching.pb.go- sizeCache protoimpl.SizeCache
campusapis/teaching/v1/teaching.pb.go-}
campusapis/teaching/v1/teaching.pb.go-
Script executed:
rg "GetSchedule.*Request" --type go -A 10 | head -50Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
campusapis/teaching/v1/teaching_grpc.pb.go: GetSchedule(ctx context.Context, in *GetScheduleRequest, opts ...grpc.CallOption) (*GetScheduleResponse, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // 获取学生/教师当前课程表
campusapis/teaching/v1/teaching_grpc.pb.go- GetScheduleNow(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetScheduleNowResponse, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // 获取学生/教师当前课程表V2 返回更详细的信息
campusapis/teaching/v1/teaching_grpc.pb.go- GetScheduleNowV2(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetScheduleNowV2Response, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // 获取学生/教师当前课程表
campusapis/teaching/v1/teaching_grpc.pb.go- GetScheduleNowV3(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetScheduleNowV3Response, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // 获取全局课表,用于推送课程信息,仅内部使用
campusapis/teaching/v1/teaching_grpc.pb.go- GetGlobalSchedule(ctx context.Context, in *GetGlobalScheduleRequest, opts ...grpc.CallOption) (*GetGlobalScheduleResponse, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // 通过CLASS_ID获取学生老师列表
campusapis/teaching/v1/teaching_grpc.pb.go- GetClassDetail(ctx context.Context, in *GetClassDetailRequest, opts ...grpc.CallOption) (*GetClassDetailResponse, error)
--
campusapis/teaching/v1/teaching_grpc.pb.go:func (c *teachingServiceClient) GetSchedule(ctx context.Context, in *GetScheduleRequest, opts ...grpc.CallOption) (*GetScheduleResponse, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
campusapis/teaching/v1/teaching_grpc.pb.go- out := new(GetScheduleResponse)
campusapis/teaching/v1/teaching_grpc.pb.go- err := c.cc.Invoke(ctx, TeachingService_GetSchedule_FullMethodName, in, out, cOpts...)
campusapis/teaching/v1/teaching_grpc.pb.go- if err != nil {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, err
campusapis/teaching/v1/teaching_grpc.pb.go- }
campusapis/teaching/v1/teaching_grpc.pb.go- return out, nil
campusapis/teaching/v1/teaching_grpc.pb.go-}
campusapis/teaching/v1/teaching_grpc.pb.go-
campusapis/teaching/v1/teaching_grpc.pb.go-func (c *teachingServiceClient) GetScheduleNow(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetScheduleNowResponse, error) {
--
campusapis/teaching/v1/teaching_grpc.pb.go: GetSchedule(context.Context, *GetScheduleRequest) (*GetScheduleResponse, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // 获取学生/教师当前课程表
campusapis/teaching/v1/teaching_grpc.pb.go- GetScheduleNow(context.Context, *emptypb.Empty) (*GetScheduleNowResponse, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // 获取学生/教师当前课程表V2 返回更详细的信息
campusapis/teaching/v1/teaching_grpc.pb.go- GetScheduleNowV2(context.Context, *emptypb.Empty) (*GetScheduleNowV2Response, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // 获取学生/教师当前课程表
campusapis/teaching/v1/teaching_grpc.pb.go- GetScheduleNowV3(context.Context, *emptypb.Empty) (*GetScheduleNowV3Response, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // 获取全局课表,用于推送课程信息,仅内部使用
campusapis/teaching/v1/teaching_grpc.pb.go- GetGlobalSchedule(context.Context, *GetGlobalScheduleRequest) (*GetGlobalScheduleResponse, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // 通过CLASS_ID获取学生老师列表
campusapis/teaching/v1/teaching_grpc.pb.go- GetClassDetail(context.Context, *GetClassDetailRequest) (*GetClassDetailResponse, error)
--
campusapis/teaching/v1/teaching_grpc.pb.go:func (UnimplementedTeachingServiceServer) GetSchedule(context.Context, *GetScheduleRequest) (*GetScheduleResponse, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, status.Errorf(codes.Unimplemented, "method GetSchedule not implemented")
campusapis/teaching/v1/teaching_grpc.pb.go-}
campusapis/teaching/v1/teaching_grpc.pb.go-func (UnimplementedTeachingServiceServer) GetScheduleNow(context.Context, *emptypb.Empty) (*GetScheduleNowResponse, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, status.Errorf(codes.Unimplemented, "method GetScheduleNow not implemented")
campusapis/teaching/v1/teaching_grpc.pb.go-}
campusapis/teaching/v1/teaching_grpc.pb.go-func (UnimplementedTeachingServiceServer) GetScheduleNowV2(context.Context, *emptypb.Empty) (*GetScheduleNowV2Response, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, status.Errorf(codes.Unimplemented, "method GetScheduleNowV2 not implemented")
campusapis/teaching/v1/teaching_grpc.pb.go-}
campusapis/teaching/v1/teaching_grpc.pb.go-func (UnimplementedTeachingServiceServer) GetScheduleNowV3(context.Context, *emptypb.Empty) (*GetScheduleNowV3Response, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, status.Errorf(codes.Unimplemented, "method GetScheduleNowV3 not implemented")
--
campusapis/teaching/v1/teaching_grpc.pb.go: in := new(GetScheduleRequest)
campusapis/teaching/v1/teaching_grpc.pb.go- if err := dec(in); err != nil {
Script executed:
grep -n "SchoolYear\|Semester" ./campusapis/teaching/v1/teaching.pb.go | head -30Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
38: Semester string `protobuf:"bytes,1,opt,name=semester,proto3" json:"semester,omitempty"`
40: SchoolYear string `protobuf:"bytes,2,opt,name=schoolYear,proto3" json:"schoolYear,omitempty"`
81:func (x *GetScheduleRequest) GetSemester() string {
83: return x.Semester
88:func (x *GetScheduleRequest) GetSchoolYear() string {
90: return x.SchoolYear
179: SemesterStartTimestamp int64 `protobuf:"varint,1,opt,name=semester_start_timestamp,json=semesterStartTimestamp,proto3" json:"semester_start_timestamp,omitempty"`
215:func (x *ScheduleResponseData) GetSemesterStartTimestamp() int64 {
217: return x.SemesterStartTimestamp
247: SchoolYear string `protobuf:"bytes,8,opt,name=SchoolYear,proto3" json:"SchoolYear,omitempty"`
249: Semester int32 `protobuf:"varint,9,opt,name=Semester,proto3" json:"Semester,omitempty"`
333:func (x *ScheduleResponseCourse) GetSchoolYear() string {
335: return x.SchoolYear
340:func (x *ScheduleResponseCourse) GetSemester() int32 {
342: return x.Semester
409: SchoolYear *schoolTime.SchoolYear `protobuf:"bytes,7,opt,name=SchoolYear,proto3" json:"SchoolYear,omitempty"`
411: Semester *schoolTime.Semester `protobuf:"bytes,8,opt,name=Semester,proto3" json:"Semester,omitempty"`
490:func (x *CourseItem) GetSchoolYear() *schoolTime.SchoolYear {
492: return x.SchoolYear
497:func (x *CourseItem) GetSemester() *schoolTime.Semester {
499: return x.Semester
1486: SchoolYear string `protobuf:"bytes,1,opt,name=schoolYear,proto3" json:"schoolYear,omitempty"`
1488: Semester string `protobuf:"bytes,2,opt,name=semester,proto3" json:"semester,omitempty"`
1523:func (x *GetClassroomsRequest) GetSchoolYear() string {
1525: return x.SchoolYear
1530:func (x *GetClassroomsRequest) GetSemester() string {
1532: return x.Semester
1540: Semester string `protobuf:"bytes,1,opt,name=semester,proto3" json:"semester,omitempty"`
1542: SchoolYear string `protobuf:"bytes,2,opt,name=schoolYear,proto3" json:"schoolYear,omitempty"`
1579:func (x *GetClassroomUsagesRequest) GetSemester() string {
Script executed:
rg "\.ToGetScheduleResponse\(\)" --type go -B 3 -A 3 | head -50Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
Script executed:
rg "type ScheduleResponseData" --type go -A 10Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
campusapis/teaching/v1/teaching.pb.go:type ScheduleResponseData struct {
campusapis/teaching/v1/teaching.pb.go- state protoimpl.MessageState `protogen:"open.v1"`
campusapis/teaching/v1/teaching.pb.go- SemesterStartTimestamp int64 `protobuf:"varint,1,opt,name=semester_start_timestamp,json=semesterStartTimestamp,proto3" json:"semester_start_timestamp,omitempty"`
campusapis/teaching/v1/teaching.pb.go- Course []*ScheduleResponseCourse `protobuf:"bytes,2,rep,name=course,proto3" json:"course,omitempty"`
campusapis/teaching/v1/teaching.pb.go- unknownFields protoimpl.UnknownFields
campusapis/teaching/v1/teaching.pb.go- sizeCache protoimpl.SizeCache
campusapis/teaching/v1/teaching.pb.go-}
campusapis/teaching/v1/teaching.pb.go-
campusapis/teaching/v1/teaching.pb.go-func (x *ScheduleResponseData) Reset() {
campusapis/teaching/v1/teaching.pb.go- *x = ScheduleResponseData{}
campusapis/teaching/v1/teaching.pb.go- mi := &file_campusapis_teaching_v1_teaching_proto_msgTypes[2]
Script executed:
rg "type Courses struct" --type go -A 15Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
campusapis/teaching/v1/teaching.pb.go:type Courses struct {
campusapis/teaching/v1/teaching.pb.go- state protoimpl.MessageState `protogen:"open.v1"`
campusapis/teaching/v1/teaching.pb.go- // 课程 map, ClassID -> 课程信息
campusapis/teaching/v1/teaching.pb.go- Items map[string]*CourseItem `protobuf:"bytes,1,rep,name=Items,proto3" json:"Items,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
campusapis/teaching/v1/teaching.pb.go- unknownFields protoimpl.UnknownFields
campusapis/teaching/v1/teaching.pb.go- sizeCache protoimpl.SizeCache
campusapis/teaching/v1/teaching.pb.go-}
campusapis/teaching/v1/teaching.pb.go-
campusapis/teaching/v1/teaching.pb.go-func (x *Courses) Reset() {
campusapis/teaching/v1/teaching.pb.go- *x = Courses{}
campusapis/teaching/v1/teaching.pb.go- mi := &file_campusapis_teaching_v1_teaching_proto_msgTypes[4]
campusapis/teaching/v1/teaching.pb.go- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
campusapis/teaching/v1/teaching.pb.go- ms.StoreMessageInfo(mi)
campusapis/teaching/v1/teaching.pb.go-}
campusapis/teaching/v1/teaching.pb.go-
campusapis/teaching/v1/teaching.pb.go-func (x *Courses) String() string {
Script executed:
rg "GetScheduleRequest" --type go -A 15 | grep -E "Semester|SchoolYear|Week" | head -20Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
campusapis/teaching/v1/teaching.pb.go- Semester string `protobuf:"bytes,1,opt,name=semester,proto3" json:"semester,omitempty"`
campusapis/teaching/v1/teaching.pb.go- SchoolYear string `protobuf:"bytes,2,opt,name=schoolYear,proto3" json:"schoolYear,omitempty"`
campusapis/teaching/v1/teaching.pb.go- Week int32 `protobuf:"varint,4,opt,name=week,proto3" json:"week,omitempty"`
campusapis/teaching/v1/teaching.pb.go- Weekday int32 `protobuf:"varint,5,opt,name=weekday,proto3" json:"weekday,omitempty"`
campusapis/teaching/v1/teaching.pb.go:func (x *GetScheduleRequest) GetSemester() string {
campusapis/teaching/v1/teaching.pb.go- return x.Semester
campusapis/teaching/v1/teaching.pb.go:func (x *GetScheduleRequest) GetSchoolYear() string {
campusapis/teaching/v1/teaching.pb.go- return x.SchoolYear
campusapis/teaching/v1/teaching.pb.go:func (x *GetScheduleRequest) GetWeek() int32 {
campusapis/teaching/v1/teaching.pb.go- return x.Week
campusapis/teaching/v1/teaching.pb.go:func (x *GetScheduleRequest) GetWeekday() int32 {
campusapis/teaching/v1/teaching.pb.go- return x.Weekday
Script executed:
cat -n ./campusapis/teaching/v1/teaching.pb.go | sed -n '30,50p'Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
30 // 优先级:
31 // 1. 若含 时间戳: 根据时间戳查询,并标记时间戳所在周(研究生暂未支持)
32 // 2. 若含 学年、学期、周次:返回整个学期课表,并标记指定周(研究生暂未支持)
33 // 3. 若含 学年、学期: 返回整个学期课表
34 // 都不命中:返回当前时间所在周的课表,并标记当前周(研究生暂未支持)
35 type GetScheduleRequest struct {
36 state protoimpl.MessageState `protogen:"open.v1"`
37 // 学期
38 Semester string `protobuf:"bytes,1,opt,name=semester,proto3" json:"semester,omitempty"`
39 // 学年 支持多种格式 如:2019-2020 2019
40 SchoolYear string `protobuf:"bytes,2,opt,name=schoolYear,proto3" json:"schoolYear,omitempty"`
41 // 时间戳
42 Timestamp int32 `protobuf:"varint,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
43 // 周次
44 Week int32 `protobuf:"varint,4,opt,name=week,proto3" json:"week,omitempty"`
45 // 星期几
46 Weekday int32 `protobuf:"varint,5,opt,name=weekday,proto3" json:"weekday,omitempty"`
47 unknownFields protoimpl.UnknownFields
48 sizeCache protoimpl.SizeCache
49 }
50
Script executed:
rg "func.*GetSchedule\(" --type go -B 2 -A 20 | head -100Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
campusapis/teaching/v1/teaching_grpc.pb.go-}
campusapis/teaching/v1/teaching_grpc.pb.go-
campusapis/teaching/v1/teaching_grpc.pb.go:func (c *teachingServiceClient) GetSchedule(ctx context.Context, in *GetScheduleRequest, opts ...grpc.CallOption) (*GetScheduleResponse, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
campusapis/teaching/v1/teaching_grpc.pb.go- out := new(GetScheduleResponse)
campusapis/teaching/v1/teaching_grpc.pb.go- err := c.cc.Invoke(ctx, TeachingService_GetSchedule_FullMethodName, in, out, cOpts...)
campusapis/teaching/v1/teaching_grpc.pb.go- if err != nil {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, err
campusapis/teaching/v1/teaching_grpc.pb.go- }
campusapis/teaching/v1/teaching_grpc.pb.go- return out, nil
campusapis/teaching/v1/teaching_grpc.pb.go-}
campusapis/teaching/v1/teaching_grpc.pb.go-
campusapis/teaching/v1/teaching_grpc.pb.go-func (c *teachingServiceClient) GetScheduleNow(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetScheduleNowResponse, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
campusapis/teaching/v1/teaching_grpc.pb.go- out := new(GetScheduleNowResponse)
campusapis/teaching/v1/teaching_grpc.pb.go- err := c.cc.Invoke(ctx, TeachingService_GetScheduleNow_FullMethodName, in, out, cOpts...)
campusapis/teaching/v1/teaching_grpc.pb.go- if err != nil {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, err
campusapis/teaching/v1/teaching_grpc.pb.go- }
campusapis/teaching/v1/teaching_grpc.pb.go- return out, nil
campusapis/teaching/v1/teaching_grpc.pb.go-}
campusapis/teaching/v1/teaching_grpc.pb.go-
campusapis/teaching/v1/teaching_grpc.pb.go-func (c *teachingServiceClient) GetScheduleNowV2(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetScheduleNowV2Response, error) {
--
campusapis/teaching/v1/teaching_grpc.pb.go-type UnimplementedTeachingServiceServer struct{}
campusapis/teaching/v1/teaching_grpc.pb.go-
campusapis/teaching/v1/teaching_grpc.pb.go:func (UnimplementedTeachingServiceServer) GetSchedule(context.Context, *GetScheduleRequest) (*GetScheduleResponse, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, status.Errorf(codes.Unimplemented, "method GetSchedule not implemented")
campusapis/teaching/v1/teaching_grpc.pb.go-}
campusapis/teaching/v1/teaching_grpc.pb.go-func (UnimplementedTeachingServiceServer) GetScheduleNow(context.Context, *emptypb.Empty) (*GetScheduleNowResponse, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, status.Errorf(codes.Unimplemented, "method GetScheduleNow not implemented")
campusapis/teaching/v1/teaching_grpc.pb.go-}
campusapis/teaching/v1/teaching_grpc.pb.go-func (UnimplementedTeachingServiceServer) GetScheduleNowV2(context.Context, *emptypb.Empty) (*GetScheduleNowV2Response, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, status.Errorf(codes.Unimplemented, "method GetScheduleNowV2 not implemented")
campusapis/teaching/v1/teaching_grpc.pb.go-}
campusapis/teaching/v1/teaching_grpc.pb.go-func (UnimplementedTeachingServiceServer) GetScheduleNowV3(context.Context, *emptypb.Empty) (*GetScheduleNowV3Response, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, status.Errorf(codes.Unimplemented, "method GetScheduleNowV3 not implemented")
campusapis/teaching/v1/teaching_grpc.pb.go-}
campusapis/teaching/v1/teaching_grpc.pb.go-func (UnimplementedTeachingServiceServer) GetGlobalSchedule(context.Context, *GetGlobalScheduleRequest) (*GetGlobalScheduleResponse, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, status.Errorf(codes.Unimplemented, "method GetGlobalSchedule not implemented")
campusapis/teaching/v1/teaching_grpc.pb.go-}
campusapis/teaching/v1/teaching_grpc.pb.go-func (UnimplementedTeachingServiceServer) GetClassDetail(context.Context, *GetClassDetailRequest) (*GetClassDetailResponse, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, status.Errorf(codes.Unimplemented, "method GetClassDetail not implemented")
campusapis/teaching/v1/teaching_grpc.pb.go-}
campusapis/teaching/v1/teaching_grpc.pb.go-func (UnimplementedTeachingServiceServer) GetClassrooms(context.Context, *GetClassroomsRequest) (*GetClassroomsResponse, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, status.Errorf(codes.Unimplemented, "method GetClassrooms not implemented")
campusapis/teaching/v1/teaching_grpc.pb.go-}
--
campusapis/teaching/v1/teaching.pb.go-}
campusapis/teaching/v1/teaching.pb.go-
campusapis/teaching/v1/teaching.pb.go:func (x *ScheduleResponseCourse) GetSchedule() []*ScheduleResponseCourse_ScheduleInfo {
campusapis/teaching/v1/teaching.pb.go- if x != nil {
campusapis/teaching/v1/teaching.pb.go- return x.Schedule
campusapis/teaching/v1/teaching.pb.go- }
campusapis/teaching/v1/teaching.pb.go- return nil
campusapis/teaching/v1/teaching.pb.go-}
campusapis/teaching/v1/teaching.pb.go-
campusapis/teaching/v1/teaching.pb.go-func (x *ScheduleResponseCourse) GetSchoolYear() string {
campusapis/teaching/v1/teaching.pb.go- if x != nil {
campusapis/teaching/v1/teaching.pb.go- return x.SchoolYear
campusapis/teaching/v1/teaching.pb.go- }
campusapis/teaching/v1/teaching.pb.go- return ""
campusapis/teaching/v1/teaching.pb.go-}
campusapis/teaching/v1/teaching.pb.go-
campusapis/teaching/v1/teaching.pb.go-func (x *ScheduleResponseCourse) GetSemester() int32 {
campusapis/teaching/v1/teaching.pb.go- if x != nil {
campusapis/teaching/v1/teaching.pb.go- return x.Semester
campusapis/teaching/v1/teaching.pb.go- }
campusapis/teaching/v1/teaching.pb.go- return 0
campusapis/teaching/v1/teaching.pb.go-}
campusapis/teaching/v1/teaching.pb.go-
--
campusapis/teaching/v1/teaching.pb.go-}
campusapis/teaching/v1/teaching.pb.go-
campusapis/teaching/v1/teaching.pb.go:func (x *CourseItem) GetSchedule() *Schedule {
campusapis/teaching/v1/teaching.pb.go- if x != nil {
campusapis/teaching/v1/teaching.pb.go- return x.Schedule
campusapis/teaching/v1/teaching.pb.go- }
campusapis/teaching/v1/teaching.pb.go- return nil
campusapis/teaching/v1/teaching.pb.go-}
campusapis/teaching/v1/teaching.pb.go-
campusapis/teaching/v1/teaching.pb.go-// 排课列表详情
campusapis/teaching/v1/teaching.pb.go-type Schedule struct {
campusapis/teaching/v1/teaching.pb.go- state protoimpl.MessageState `protogen:"open.v1"`
campusapis/teaching/v1/teaching.pb.go- // 排课 map, 排课ID -> 排课信息
campusapis/teaching/v1/teaching.pb.go- Items map[string]*ScheduleItem `protobuf:"bytes,1,rep,name=Items,proto3" json:"Items,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
campusapis/teaching/v1/teaching.pb.go- unknownFields protoimpl.UnknownFields
campusapis/teaching/v1/teaching.pb.go- sizeCache protoimpl.SizeCache
campusapis/teaching/v1/teaching.pb.go-}
campusapis/teaching/v1/teaching.pb.go-
campusapis/teaching/v1/teaching.pb.go-func (x *Schedule) Reset() {
campusapis/teaching/v1/teaching.pb.go- *x = Schedule{}
campusapis/teaching/v1/teaching.pb.go- mi := &file_campusapis_teaching_v1_teaching_proto_msgTypes[6]
campusapis/teaching/v1/teaching.pb.go- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
campusapis/teaching/v1/teaching.pb.go- ms.StoreMessageInfo(mi)
--
aggregatingapis/infostream/v1/infostream.pb.go-}
aggregatingapis/infostream/v1/infostream.pb.go-
aggregatingapis/infostream/v1/infostream.pb.go:func (x *InfoStreamData) GetSchedule() *ScheduleResp {
aggregatingapis/infostream/v1/infostream.pb.go- if x != nil {
Script executed:
rg "type CourseItem struct" --type go -A 20Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
campusapis/teaching/v1/teaching.pb.go:type CourseItem struct {
campusapis/teaching/v1/teaching.pb.go- state protoimpl.MessageState `protogen:"open.v1"`
campusapis/teaching/v1/teaching.pb.go- // 课程内部ID
campusapis/teaching/v1/teaching.pb.go- ClassID string `protobuf:"bytes,1,opt,name=ClassID,proto3" json:"ClassID,omitempty"`
campusapis/teaching/v1/teaching.pb.go- // 选课号
campusapis/teaching/v1/teaching.pb.go- ClassName string `protobuf:"bytes,2,opt,name=ClassName,proto3" json:"ClassName,omitempty"`
campusapis/teaching/v1/teaching.pb.go- // 课程代码
campusapis/teaching/v1/teaching.pb.go- CourseID string `protobuf:"bytes,3,opt,name=CourseID,proto3" json:"CourseID,omitempty"`
campusapis/teaching/v1/teaching.pb.go- // 课程中文名
campusapis/teaching/v1/teaching.pb.go- CourseName string `protobuf:"bytes,4,opt,name=CourseName,proto3" json:"CourseName,omitempty"`
campusapis/teaching/v1/teaching.pb.go- // 上课时间中文,如: 星期一第6-7节{1-2周};星期一第6-7节{3-17周}
campusapis/teaching/v1/teaching.pb.go- ClassTime string `protobuf:"bytes,5,opt,name=ClassTime,proto3" json:"ClassTime,omitempty"`
campusapis/teaching/v1/teaching.pb.go- // 学分
campusapis/teaching/v1/teaching.pb.go- Credit string `protobuf:"bytes,6,opt,name=Credit,proto3" json:"Credit,omitempty"`
campusapis/teaching/v1/teaching.pb.go- // 学年
campusapis/teaching/v1/teaching.pb.go- SchoolYear *schoolTime.SchoolYear `protobuf:"bytes,7,opt,name=SchoolYear,proto3" json:"SchoolYear,omitempty"`
campusapis/teaching/v1/teaching.pb.go- // 学期
campusapis/teaching/v1/teaching.pb.go- Semester *schoolTime.Semester `protobuf:"bytes,8,opt,name=Semester,proto3" json:"Semester,omitempty"`
campusapis/teaching/v1/teaching.pb.go- // 排课详情
campusapis/teaching/v1/teaching.pb.go- Schedule *Schedule `protobuf:"bytes,9,opt,name=Schedule,proto3" json:"Schedule,omitempty"`
campusapis/teaching/v1/teaching.pb.go- unknownFields protoimpl.UnknownFields
Script executed:
rg "type SchoolYear" --type go -B 2 -A 10 | head -50Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
campusapis/schoolTime/defined.pb.go-
campusapis/schoolTime/defined.pb.go-// 学年
campusapis/schoolTime/defined.pb.go:type SchoolYear struct {
campusapis/schoolTime/defined.pb.go- state protoimpl.MessageState `protogen:"open.v1"`
campusapis/schoolTime/defined.pb.go- // 学年开始年,如:2021-2022 学年为 2021
campusapis/schoolTime/defined.pb.go- Year int32 `protobuf:"varint,1,opt,name=Year,proto3" json:"Year,omitempty"`
campusapis/schoolTime/defined.pb.go- unknownFields protoimpl.UnknownFields
campusapis/schoolTime/defined.pb.go- sizeCache protoimpl.SizeCache
campusapis/schoolTime/defined.pb.go-}
campusapis/schoolTime/defined.pb.go-
campusapis/schoolTime/defined.pb.go-func (x *SchoolYear) Reset() {
campusapis/schoolTime/defined.pb.go- *x = SchoolYear{}
campusapis/schoolTime/defined.pb.go- mi := &file_campusapis_schoolTime_defined_proto_msgTypes[1]
Script executed:
rg "ToGetScheduleResponse\(" --type go -B 5 -A 2Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
campusapis/teaching/v1/courses.go-import (
campusapis/teaching/v1/courses.go- "github.com/hduhelp/api_open_sdk/campusapis/staff"
campusapis/teaching/v1/courses.go- "github.com/hduhelp/api_open_sdk/schoolConst"
campusapis/teaching/v1/courses.go-)
campusapis/teaching/v1/courses.go-
campusapis/teaching/v1/courses.go:func (x *Courses) ToGetScheduleResponse() *GetScheduleResponse {
campusapis/teaching/v1/courses.go- return &GetScheduleResponse{
campusapis/teaching/v1/courses.go- Data: &ScheduleResponseData{
--
campusapis/teaching/v1/courses.go- list = append(list, v.ToScheduleResponseCourse())
campusapis/teaching/v1/courses.go- }
campusapis/teaching/v1/courses.go- return list
campusapis/teaching/v1/courses.go-}
campusapis/teaching/v1/courses.go-
campusapis/teaching/v1/courses.go:func (i CourseItems) ToGetScheduleResponse() (list []*ScheduleResponseCourse) {
campusapis/teaching/v1/courses.go- list = make([]*ScheduleResponseCourse, 0)
campusapis/teaching/v1/courses.go- for _, v := range i {
Script executed:
rg "type Semester struct" --type go -A 10 | head -30Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
campusapis/schoolTime/defined.pb.go:type Semester struct {
campusapis/schoolTime/defined.pb.go- state protoimpl.MessageState `protogen:"open.v1"`
campusapis/schoolTime/defined.pb.go- Num int32 `protobuf:"varint,1,opt,name=Num,proto3" json:"Num,omitempty"`
campusapis/schoolTime/defined.pb.go- unknownFields protoimpl.UnknownFields
campusapis/schoolTime/defined.pb.go- sizeCache protoimpl.SizeCache
campusapis/schoolTime/defined.pb.go-}
campusapis/schoolTime/defined.pb.go-
campusapis/schoolTime/defined.pb.go-func (x *Semester) Reset() {
campusapis/schoolTime/defined.pb.go- *x = Semester{}
campusapis/schoolTime/defined.pb.go- mi := &file_campusapis_schoolTime_defined_proto_msgTypes[2]
campusapis/schoolTime/defined.pb.go- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
Script executed:
rg "SemesterStartTimestamp" --type go | head -20Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
schoolConst/const.go: SemesterStartTimestamp = int64(1757865600) // 2025-9-15 00:00:00
schoolConst/const.go: timeStart := SemesterStartTimestamp
schoolConst/const.go: SemesterStartTimestamp int64 `json:"semester_start_timestamp"`
schoolConst/const.go: SemesterStartTimestamp: SemesterStartTimestamp,
gatewayapis/auth/v1/auth.pb.go: SemesterStartTimestamp int32 `protobuf:"varint,3,opt,name=semester_start_timestamp,json=semesterStartTimestamp,proto3" json:"semester_start_timestamp,omitempty"`
gatewayapis/auth/v1/auth.pb.go:func (x *SchoolTime) GetSemesterStartTimestamp() int32 {
gatewayapis/auth/v1/auth.pb.go: return x.SemesterStartTimestamp
campusapis/teaching/v1/courses.go: SemesterStartTimestamp: schoolConst.SemesterStartTimestamp,
campusapis/teaching/v1/teaching.pb.go: SemesterStartTimestamp int64 `protobuf:"varint,1,opt,name=semester_start_timestamp,json=semesterStartTimestamp,proto3" json:"semester_start_timestamp,omitempty"`
campusapis/teaching/v1/teaching.pb.go:func (x *ScheduleResponseData) GetSemesterStartTimestamp() int64 {
campusapis/teaching/v1/teaching.pb.go: return x.SemesterStartTimestamp
campusapis/teaching/v1/scheduleProcess.go:const timeStart = schoolConst.SemesterStartTimestamp
aggregatingapis/time/v1/time.pb.go: SemesterStartTimestamp int64 `protobuf:"varint,3,opt,name=semesterStartTimestamp,proto3" json:"semesterStartTimestamp,omitempty"`
aggregatingapis/time/v1/time.pb.go:func (x *TimeData) GetSemesterStartTimestamp() int64 {
aggregatingapis/time/v1/time.pb.go: return x.SemesterStartTimestamp
Script executed:
find . -type f -name "*.proto" | xargs grep -l "GetScheduleRequest\|GetScheduleResponse" 2>/dev/null | head -5Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
./campusapis/teaching/v1/teaching.proto
Script executed:
cat -n ./campusapis/teaching/v1/teaching.proto | grep -A 10 -B 10 "SemesterStartTimestamp\|GetScheduleRequest\|GetScheduleResponse" | head -80Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
24 url: "https://github.com/grpc-ecosystem/grpc-gateway/blob/master/LICENSE.txt";
25 };
26 };
27 schemes: HTTPS;
28 consumes: "application/json";
29 produces: "application/json";
30 };
31
32 service TeachingService {
33 // 获取学生/教师课程表
34 rpc GetSchedule(GetScheduleRequest) returns (GetScheduleResponse) {
35 option (google.api.http) = {
36 get: "/teaching/v1/schedule"
37 additional_bindings {
38 get: "/teaching/schedule"
39 }
40 additional_bindings {
41 get: "/student/v2/schedule"
42 }
43 };
44 }
--
174 get: "/teaching/v1/class/query/fav/rank"
175 additional_bindings {
176 get: "/teaching/class/query/fav/rank"
177 }
178 };
179 }
180 }
181
182
183
184 // GetScheduleRequest 根据参数和预设优先级拼装查询日期
185 // 优先级:
186 // 1. 若含 时间戳: 根据时间戳查询,并标记时间戳所在周(研究生暂未支持)
187 // 2. 若含 学年、学期、周次:返回整个学期课表,并标记指定周(研究生暂未支持)
188 // 3. 若含 学年、学期: 返回整个学期课表
189 // 都不命中:返回当前时间所在周的课表,并标记当前周(研究生暂未支持)
190 message GetScheduleRequest {
191 //学期
192 string semester = 1;
193 //学年 支持多种格式 如:2019-2020 2019
194 string schoolYear = 2;
195 //时间戳
196 int32 timestamp = 3;
197 //周次
198 int32 week = 4;
199 //星期几
200 int32 weekday = 5;
201 }
202
203 // GetScheduleResponse 课表列表返回体
204 message GetScheduleResponse {
205 int32 error = 1;
206 string msg = 2;
207 ScheduleResponseData data = 3;
208 }
209
210 message ScheduleResponseData {
211 int64 semester_start_timestamp = 1;
212 repeated ScheduleResponseCourse course = 2;
213 }
214
Script executed:
rg "func.*GetSchedule" --type go -B 5 | grep -E "func|GetSchedule|Request|server" | head -40Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
campusapis/teaching/v1/courses.go:func (x *Courses) ToGetScheduleResponse() *GetScheduleResponse {
campusapis/teaching/v1/courses.go:func (x *Courses) GetScheduleResponseCourse() (list []*ScheduleResponseCourse) {
campusapis/teaching/v1/courses.go:func (i CourseItems) ToGetScheduleResponse() (list []*ScheduleResponseCourse) {
campusapis/teaching/v1/courses.go:func (x *CourseItem) GetScheduleResponseCourse_Schedule() (list []*ScheduleResponseCourse_ScheduleInfo) {
campusapis/teaching/v1/teaching_grpc.pb.go-func NewTeachingServiceClient(cc grpc.ClientConnInterface) TeachingServiceClient {
campusapis/teaching/v1/teaching_grpc.pb.go:func (c *teachingServiceClient) GetSchedule(ctx context.Context, in *GetScheduleRequest, opts ...grpc.CallOption) (*GetScheduleResponse, error) {
campusapis/teaching/v1/teaching_grpc.pb.go:func (c *teachingServiceClient) GetScheduleNow(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetScheduleNowResponse, error) {
campusapis/teaching/v1/teaching_grpc.pb.go:func (c *teachingServiceClient) GetScheduleNowV2(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetScheduleNowV2Response, error) {
campusapis/teaching/v1/teaching_grpc.pb.go:func (c *teachingServiceClient) GetScheduleNowV3(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetScheduleNowV3Response, error) {
campusapis/teaching/v1/teaching_grpc.pb.go:func (UnimplementedTeachingServiceServer) GetSchedule(context.Context, *GetScheduleRequest) (*GetScheduleResponse, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, status.Errorf(codes.Unimplemented, "method GetSchedule not implemented")
campusapis/teaching/v1/teaching_grpc.pb.go:func (UnimplementedTeachingServiceServer) GetScheduleNow(context.Context, *emptypb.Empty) (*GetScheduleNowResponse, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, status.Errorf(codes.Unimplemented, "method GetScheduleNow not implemented")
campusapis/teaching/v1/teaching_grpc.pb.go:func (UnimplementedTeachingServiceServer) GetScheduleNowV2(context.Context, *emptypb.Empty) (*GetScheduleNowV2Response, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, status.Errorf(codes.Unimplemented, "method GetScheduleNowV2 not implemented")
campusapis/teaching/v1/teaching_grpc.pb.go:func (UnimplementedTeachingServiceServer) GetScheduleNowV3(context.Context, *emptypb.Empty) (*GetScheduleNowV3Response, error) {
campusapis/teaching/v1/teaching_grpc.pb.go:func _TeachingService_GetSchedule_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return srv.(TeachingServiceServer).GetSchedule(ctx, req.(*GetScheduleRequest))
campusapis/teaching/v1/teaching_grpc.pb.go:func _TeachingService_GetScheduleNow_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return srv.(TeachingServiceServer).GetScheduleNow(ctx, req.(*emptypb.Empty))
campusapis/teaching/v1/teaching_grpc.pb.go:func _TeachingService_GetScheduleNowV2_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return srv.(TeachingServiceServer).GetScheduleNowV2(ctx, req.(*emptypb.Empty))
campusapis/teaching/v1/teaching_grpc.pb.go:func _TeachingService_GetScheduleNowV3_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
campusapis/teaching/v1/teaching.pb.go:func (x *GetScheduleRequest) Reset() {
campusapis/teaching/v1/teaching.pb.go:func (x *GetScheduleRequest) String() string {
campusapis/teaching/v1/teaching.pb.go:func (*GetScheduleRequest) ProtoMessage() {}
campusapis/teaching/v1/teaching.pb.go:func (x *GetScheduleRequest) ProtoReflect() protoreflect.Message {
campusapis/teaching/v1/teaching.pb.go-// Deprecated: Use GetScheduleRequest.ProtoReflect.Descriptor instead.
campusapis/teaching/v1/teaching.pb.go:func (*GetScheduleRequest) Descriptor() ([]byte, []int) {
campusapis/teaching/v1/teaching.pb.go:func (x *GetScheduleRequest) GetSemester() string {
campusapis/teaching/v1/teaching.pb.go:func (x *GetScheduleRequest) GetSchoolYear() string {
campusapis/teaching/v1/teaching.pb.go:func (x *GetScheduleRequest) GetTimestamp() int32 {
campusapis/teaching/v1/teaching.pb.go:func (x *GetScheduleRequest) GetWeek() int32 {
campusapis/teaching/v1/teaching.pb.go:func (x *GetScheduleRequest) GetWeekday() int32 {
campusapis/teaching/v1/teaching.pb.go:func (x *GetScheduleResponse) Reset() {
campusapis/teaching/v1/teaching.pb.go:func (x *GetScheduleResponse) String() string {
campusapis/teaching/v1/teaching.pb.go:func (*GetScheduleResponse) ProtoMessage() {}
campusapis/teaching/v1/teaching.pb.go:func (x *GetScheduleResponse) ProtoReflect() protoreflect.Message {
campusapis/teaching/v1/teaching.pb.go-// Deprecated: Use GetScheduleResponse.ProtoReflect.Descriptor instead.
campusapis/teaching/v1/teaching.pb.go:func (*GetScheduleResponse) Descriptor() ([]byte, []int) {
Script executed:
find . -type f -name "*.go" -path "*/teaching/*" | xargs grep -l "GetScheduleRequest" | grep -v "pb.go" | grep -v "test"Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
./campusapis/teaching/v1/teaching.pb.gw.go
Script executed:
rg "TeachingServiceServer" --type go -A 30 | grep -A 30 "GetSchedule.*Request" | head -60Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
campusapis/teaching/v1/teaching_grpc.pb.go- GetSchedule(context.Context, *GetScheduleRequest) (*GetScheduleResponse, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // 获取学生/教师当前课程表
campusapis/teaching/v1/teaching_grpc.pb.go- GetScheduleNow(context.Context, *emptypb.Empty) (*GetScheduleNowResponse, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // 获取学生/教师当前课程表V2 返回更详细的信息
campusapis/teaching/v1/teaching_grpc.pb.go- GetScheduleNowV2(context.Context, *emptypb.Empty) (*GetScheduleNowV2Response, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // 获取学生/教师当前课程表
campusapis/teaching/v1/teaching_grpc.pb.go- GetScheduleNowV3(context.Context, *emptypb.Empty) (*GetScheduleNowV3Response, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // 获取全局课表,用于推送课程信息,仅内部使用
campusapis/teaching/v1/teaching_grpc.pb.go- GetGlobalSchedule(context.Context, *GetGlobalScheduleRequest) (*GetGlobalScheduleResponse, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // 通过CLASS_ID获取学生老师列表
campusapis/teaching/v1/teaching_grpc.pb.go- GetClassDetail(context.Context, *GetClassDetailRequest) (*GetClassDetailResponse, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // 获取所有教室列表
campusapis/teaching/v1/teaching_grpc.pb.go- GetClassrooms(context.Context, *GetClassroomsRequest) (*GetClassroomsResponse, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // 获取某一教室的使用情况
campusapis/teaching/v1/teaching_grpc.pb.go- GetClassroomUsages(context.Context, *GetClassroomUsagesRequest) (*GetClassroomUsagesResponse, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // 获取所有空教室列表
campusapis/teaching/v1/teaching_grpc.pb.go- GetUnusedClassrooms(context.Context, *GetUnusedClassroomsRequest) (*GetUnusedClassroomsResponse, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // 课程查询
campusapis/teaching/v1/teaching_grpc.pb.go- ClassQuerySearch(context.Context, *ClassQuerySearchRequest) (*ClassQuerySearchResponse, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // magic字段映射表
campusapis/teaching/v1/teaching_grpc.pb.go- ClassQueryMap(context.Context, *emptypb.Empty) (*ClassQueryMapResponse, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // 设置课程收藏
campusapis/teaching/v1/teaching_grpc.pb.go- ClassQueryFavSet(context.Context, *ClassQueryFavSetRequest) (*ClassQueryFavSetResponse, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // 获取课程收藏
campusapis/teaching/v1/teaching_grpc.pb.go- ClassQueryFavGet(context.Context, *emptypb.Empty) (*ClassQueryFavGetResponse, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // 按classIDs获取课程信息
campusapis/teaching/v1/teaching_grpc.pb.go- ClassQueryGet(context.Context, *ClassQueryGetRequest) (*ClassQueryGetResponse, error)
campusapis/teaching/v1/teaching_grpc.pb.go- // 获取收藏排行
campusapis/teaching/v1/teaching_grpc.pb.go- ClassQueryFavRank(context.Context, *emptypb.Empty) (*ClassQueryFavRankResponse, error)
campusapis/teaching/v1/teaching_grpc.pb.go: mustEmbedUnimplementedTeachingServiceServer()
campusapis/teaching/v1/teaching_grpc.pb.go-}
--
campusapis/teaching/v1/teaching_grpc.pb.go:func (UnimplementedTeachingServiceServer) GetSchedule(context.Context, *GetScheduleRequest) (*GetScheduleResponse, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, status.Errorf(codes.Unimplemented, "method GetSchedule not implemented")
campusapis/teaching/v1/teaching_grpc.pb.go-}
campusapis/teaching/v1/teaching_grpc.pb.go:func (UnimplementedTeachingServiceServer) GetScheduleNow(context.Context, *emptypb.Empty) (*GetScheduleNowResponse, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, status.Errorf(codes.Unimplemented, "method GetScheduleNow not implemented")
campusapis/teaching/v1/teaching_grpc.pb.go-}
campusapis/teaching/v1/teaching_grpc.pb.go:func (UnimplementedTeachingServiceServer) GetScheduleNowV2(context.Context, *emptypb.Empty) (*GetScheduleNowV2Response, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, status.Errorf(codes.Unimplemented, "method GetScheduleNowV2 not implemented")
campusapis/teaching/v1/teaching_grpc.pb.go-}
campusapis/teaching/v1/teaching_grpc.pb.go:func (UnimplementedTeachingServiceServer) GetScheduleNowV3(context.Context, *emptypb.Empty) (*GetScheduleNowV3Response, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, status.Errorf(codes.Unimplemented, "method GetScheduleNowV3 not implemented")
campusapis/teaching/v1/teaching_grpc.pb.go-}
campusapis/teaching/v1/teaching_grpc.pb.go:func (UnimplementedTeachingServiceServer) GetGlobalSchedule(context.Context, *GetGlobalScheduleRequest) (*GetGlobalScheduleResponse, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, status.Errorf(codes.Unimplemented, "method GetGlobalSchedule not implemented")
campusapis/teaching/v1/teaching_grpc.pb.go-}
campusapis/teaching/v1/teaching_grpc.pb.go:func (UnimplementedTeachingServiceServer) GetClassDetail(context.Context, *GetClassDetailRequest) (*GetClassDetailResponse, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, status.Errorf(codes.Unimplemented, "method GetClassDetail not implemented")
campusapis/teaching/v1/teaching_grpc.pb.go-}
campusapis/teaching/v1/teaching_grpc.pb.go:func (UnimplementedTeachingServiceServer) GetClassrooms(context.Context, *GetClassroomsRequest) (*GetClassroomsResponse, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, status.Errorf(codes.Unimplemented, "method GetClassrooms not implemented")
campusapis/teaching/v1/teaching_grpc.pb.go-}
campusapis/teaching/v1/teaching_grpc.pb.go:func (UnimplementedTeachingServiceServer) GetClassroomUsages(context.Context, *GetClassroomUsagesRequest) (*GetClassroomUsagesResponse, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, status.Errorf(codes.Unimplemented, "method GetClassroomUsages not implemented")
campusapis/teaching/v1/teaching_grpc.pb.go-}
campusapis/teaching/v1/teaching_grpc.pb.go:func (UnimplementedTeachingServiceServer) GetUnusedClassrooms(context.Context, *GetUnusedClassroomsRequest) (*GetUnusedClassroomsResponse, error) {
campusapis/teaching/v1/teaching_grpc.pb.go- return nil, status.Errorf(codes.Unimplemented, "method GetUnusedClassrooms not implemented")
campusapis/teaching/v1/teaching_grpc.pb.go-}
campusapis/teaching/v1/teaching_grpc.pb.go:func (UnimplementedTeachingServiceServer) ClassQuerySearch(context.Context, *ClassQuerySearchRequest) (*ClassQuerySearchResponse, error) {
Script executed:
grep -n "ToGetScheduleResponse\|\.GetSchedule\|TeachingServiceServer" ./campusapis/teaching/v1/teaching.pb.gw.go | head -30Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
52: msg, err := client.GetSchedule(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
56:func local_request_TeachingService_GetSchedule_0(ctx context.Context, marshaler runtime.Marshaler, server TeachingServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
67: msg, err := server.GetSchedule(ctx, &protoReq)
84: msg, err := client.GetSchedule(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
88:func local_request_TeachingService_GetSchedule_1(ctx context.Context, marshaler runtime.Marshaler, server TeachingServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
99: msg, err := server.GetSchedule(ctx, &protoReq)
116: msg, err := client.GetSchedule(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
120:func local_request_TeachingService_GetSchedule_2(ctx context.Context, marshaler runtime.Marshaler, server TeachingServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
131: msg, err := server.GetSchedule(ctx, &protoReq)
140: msg, err := client.GetScheduleNow(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
144:func local_request_TeachingService_GetScheduleNow_0(ctx context.Context, marshaler runtime.Marshaler, server TeachingServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
149: msg, err := server.GetScheduleNow(ctx, &protoReq)
158: msg, err := client.GetScheduleNow(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
162:func local_request_TeachingService_GetScheduleNow_1(ctx context.Context, marshaler runtime.Marshaler, server TeachingServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
167: msg, err := server.GetScheduleNow(ctx, &protoReq)
176: msg, err := client.GetScheduleNowV2(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
180:func local_request_TeachingService_GetScheduleNowV2_0(ctx context.Context, marshaler runtime.Marshaler, server TeachingServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
185: msg, err := server.GetScheduleNowV2(ctx, &protoReq)
194: msg, err := client.GetScheduleNowV2(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
198:func local_request_TeachingService_GetScheduleNowV2_1(ctx context.Context, marshaler runtime.Marshaler, server TeachingServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
203: msg, err := server.GetScheduleNowV2(ctx, &protoReq)
212: msg, err := client.GetScheduleNowV3(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
216:func local_request_TeachingService_GetScheduleNowV3_0(ctx context.Context, marshaler runtime.Marshaler, server TeachingServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
221: msg, err := server.GetScheduleNowV3(ctx, &protoReq)
242:func local_request_TeachingService_GetGlobalSchedule_0(ctx context.Context, marshaler runtime.Marshaler, server TeachingServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
274:func local_request_TeachingService_GetClassDetail_0(ctx context.Context, marshaler runtime.Marshaler, server TeachingServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
306:func local_request_TeachingService_GetClassDetail_1(ctx context.Context, marshaler runtime.Marshaler, server TeachingServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
338:func local_request_TeachingService_GetClassrooms_0(ctx context.Context, marshaler runtime.Marshaler, server TeachingServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
370:func local_request_TeachingService_GetClassrooms_1(ctx context.Context, marshaler runtime.Marshaler, server TeachingServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
402:func local_request_TeachingService_GetClassroomUsages_0(ctx context.Context, marshaler runtime.Marshaler, server TeachingServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
Script executed:
find . -type f -name "*.go" -path "*/teaching/*" ! -name "*pb.go" ! -name "*test*" -exec grep -l "GetScheduleRequest\|GetScheduleResponse" {} \;Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
./campusapis/teaching/v1/teaching.pb.gw.go
./campusapis/teaching/v1/courses.go
Script executed:
cat -n ./campusapis/teaching/v1/teaching.pb.gw.go | sed -n '52,75p'Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
52 msg, err := client.GetSchedule(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
53 return msg, metadata, err
54 }
55
56 func local_request_TeachingService_GetSchedule_0(ctx context.Context, marshaler runtime.Marshaler, server TeachingServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
57 var (
58 protoReq GetScheduleRequest
59 metadata runtime.ServerMetadata
60 )
61 if err := req.ParseForm(); err != nil {
62 return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
63 }
64 if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_TeachingService_GetSchedule_0); err != nil {
65 return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
66 }
67 msg, err := server.GetSchedule(ctx, &protoReq)
68 return msg, metadata, err
69 }
70
71 var filter_TeachingService_GetSchedule_1 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
72
73 func request_TeachingService_GetSchedule_1(ctx context.Context, marshaler runtime.Marshaler, client TeachingServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
74 var (
75 protoReq GetScheduleRequest
Script executed:
rg "server\.GetSchedule\|\.ToGetScheduleResponse" --type go -B 5 -A 10 | head -80Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
Script executed:
find . -type f -name "*.go" ! -name "*pb*" ! -name "*test*" -exec grep -l "GetSchedule\|ToGetScheduleResponse" {} \; | head -10Repository: hduhelp/api_open_sdk
Repository: hduhelp/api_open_sdk
Exit code: 0
stdout:
./campusapis/teaching/v1/courses.go
SemesterStartTimestamp 使用固定常量,查询其他学期时会返回错误的时间戳
GetScheduleRequest 支持指定学年/学期查询(见 proto 注释中的优先级说明),但 ToGetScheduleResponse() 直接使用固定常量 schoolConst.SemesterStartTimestamp,会导致查询历史学期或未来学期时返回错误的时间戳。建议该方法接收正确的学期开始时间戳作为参数,由调用方根据请求的学年/学期计算并传入。
🤖 Prompt for AI Agents
In `@campusapis/teaching/v1/courses.go` around lines 3 - 13, The
ToGetScheduleResponse method currently hardcodes SemesterStartTimestamp using
schoolConst.SemesterStartTimestamp which breaks queries for non-default terms;
change the signature of Courses.ToGetScheduleResponse (the method on type
Courses) to accept a semesterStartTimestamp parameter and set
ScheduleResponseData.SemesterStartTimestamp to that parameter instead of
schoolConst.SemesterStartTimestamp, and update callers to compute/lookup the
correct semester start timestamp based on the GetScheduleRequest (year/term) and
pass it into ToGetScheduleResponse so historical/future term queries return the
correct value.
| "post": { | ||
| "summary": "新增或更新体测成绩", | ||
| "operationId": "FitnessService_StoreFitnessScore2", | ||
| "responses": { | ||
| "200": { | ||
| "description": "A successful response.", | ||
| "schema": { | ||
| "$ref": "#/definitions/v1StoreFitnessScoreResponse" | ||
| } | ||
| }, | ||
| "default": { | ||
| "description": "An unexpected error response.", | ||
| "schema": { | ||
| "$ref": "#/definitions/rpcStatus" | ||
| } | ||
| } | ||
| }, | ||
| "parameters": [ | ||
| { | ||
| "name": "staffId", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "string" | ||
| }, | ||
| { | ||
| "name": "schoolYear", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "string" | ||
| }, | ||
| { | ||
| "name": "semester", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "integer", | ||
| "format": "int32" | ||
| }, | ||
| { | ||
| "name": "gender", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "string" | ||
| }, | ||
| { | ||
| "name": "grade", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "integer", | ||
| "format": "int32" | ||
| }, | ||
| { | ||
| "name": "height", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "number", | ||
| "format": "float" | ||
| }, | ||
| { | ||
| "name": "weight", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "number", | ||
| "format": "float" | ||
| }, | ||
| { | ||
| "name": "bmi", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "number", | ||
| "format": "float" | ||
| }, | ||
| { | ||
| "name": "run50m", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "number", | ||
| "format": "float" | ||
| }, | ||
| { | ||
| "name": "standingLongJump", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "number", | ||
| "format": "float" | ||
| }, | ||
| { | ||
| "name": "sitAndReach", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "number", | ||
| "format": "float" | ||
| }, | ||
| { | ||
| "name": "run800m", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "number", | ||
| "format": "float" | ||
| }, | ||
| { | ||
| "name": "run1000m", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "number", | ||
| "format": "float" | ||
| }, | ||
| { | ||
| "name": "sitUps", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "integer", | ||
| "format": "int32" | ||
| }, | ||
| { | ||
| "name": "pullUps", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "integer", | ||
| "format": "int32" | ||
| }, | ||
| { | ||
| "name": "lungCapacity", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "integer", | ||
| "format": "int32" | ||
| }, | ||
| { | ||
| "name": "totalScore", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "number", | ||
| "format": "float" | ||
| } | ||
| ], | ||
| "tags": [ | ||
| "FitnessService" | ||
| ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# First, let's find the swagger file and check its structure
find . -type f -name "fitness.swagger.json" 2>/dev/null | head -5Repository: hduhelp/api_open_sdk
Length of output: 121
🏁 Script executed:
# Also check for related proto files
find . -type f -name "*.proto" -path "*fitness*" 2>/dev/null | head -10Repository: hduhelp/api_open_sdk
Length of output: 101
🏁 Script executed:
# Let's examine the swagger file to see the full structure
wc -l docs/swagger/campusapis/fitness/v1/fitness.swagger.jsonRepository: hduhelp/api_open_sdk
Length of output: 123
🏁 Script executed:
# Read the full swagger file to see all endpoints
cat docs/swagger/campusapis/fitness/v1/fitness.swagger.jsonRepository: hduhelp/api_open_sdk
Length of output: 17538
🏁 Script executed:
# Read the proto file to see the endpoint definitions and additional_bindings
cat campusapis/fitness/v1/fitness.protoRepository: hduhelp/api_open_sdk
Length of output: 2958
在 proto 文件中为 additional_bindings 添加 body: "*" 配置
根据 proto 文件分析,StoreFitnessScore 和 UpdateFitnessScore 的 additional_bindings 缺少 body: "*" 配置,导致 Swagger 生成器将这些额外绑定的所有字段解释为 query 参数。这造成:
/fitness/score的 POST 和 PATCH 使用 query 参数/fitness/v1/score的 POST 和 PATCH 使用 body 参数
需要在 proto 中修改:
rpc StoreFitnessScore(StoreFitnessScoreRequest) returns (StoreFitnessScoreResponse) {
option (google.api.http) = {
post: "/fitness/v1/score"
body: "*"
additional_bindings {
post: "/fitness/score"
body: "*" // 添加此行
}
};
}
rpc UpdateFitnessScore(UpdateFitnessScoreRequest) returns (UpdateFitnessScoreResponse) {
option (google.api.http) = {
patch: "/fitness/v1/score"
body: "*"
additional_bindings {
patch: "/fitness/score"
body: "*" // 添加此行
}
};
}修改后重新生成 Swagger 文件。
🧰 Tools
🪛 Checkov (3.2.334)
[medium] 62-199: Ensure that operation objects have 'consumes' field defined for PUT, POST and PATCH operations - version 2.0 files
(CKV_OPENAPI_17)
🤖 Prompt for AI Agents
In `@docs/swagger/campusapis/fitness/v1/fitness.swagger.json` around lines 62 -
199, The Swagger shows POST/PATCH to /fitness/score being rendered as query
params because the proto RPCs StoreFitnessScore and UpdateFitnessScore omitted
body: "*" in their additional_bindings; update both RPC options so each
additional_bindings block for StoreFitnessScore and UpdateFitnessScore includes
body: "*" (matching the primary binding), then regenerate the Swagger to ensure
/fitness/score endpoints use request body instead of query parameters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@docs/swagger/campusapis/staff/v1/campus.swagger.json`:
- Around line 37-56: The DELETE operation currently has its identifying query
parameters marked as optional; update the parameter definitions for "staffId",
"schoolYear", and "semester" to "required": true in the Swagger spec so callers
must supply them, or preferably add field behavior annotations in the proto
(e.g., google.api.field_behavior = REQUIRED on those fields) and regenerate the
swagger; also add server-side validation in the delete handler to enforce
presence/validity of staffId/schoolYear/semester before performing deletion.
- Around line 19-200: The POST/PATCH endpoints for /fitness/score are using
query params because the proto additional_bindings for StoreFitnessScore and
UpdateFitnessScore lack a body declaration; open the rpc definitions
StoreFitnessScore(StoreFitnessScoreRequest) and
UpdateFitnessScore(UpdateFitnessScoreRequest) in campus.proto and add body: "*"
inside each additional_bindings block that binds to "/fitness/score" (so the
additional_bindings post/patch entries include body: "*"), then regenerate the
swagger so those endpoints accept the request body instead of query parameters.
🧹 Nitpick comments (5)
campusapis/staff/v1/campus.proto (4)
209-241: RPC 定义结构良好,但存在几点设计考虑。
缺少读取操作:有 Store、Update、Delete,但没有
GetFitnessScore用于查询体测成绩。建议补充完整 CRUD 操作。语义重叠:
StoreFitnessScore描述为"新增或更新"(upsert),而UpdateFitnessScore为"更新"。两者功能重叠,可能造成 API 使用者困惑。建议:
- 要么只保留
StoreFitnessScore(upsert 语义)- 要么将
StoreFitnessScore改为纯CreateFitnessScore(仅新增)
871-889: 字段命名风格与文件其他部分不一致。新增的消息使用
snake_case(如staff_id、school_year),而文件中已有消息均使用camelCase(如staffId、schoolYear)。建议保持一致性。♻️ 建议修改为 camelCase
message StoreFitnessScoreRequest { - string staff_id = 1; - string school_year = 2; + string staffId = 1; + string schoolYear = 2; int32 semester = 3; string gender = 4; int32 grade = 5; float height = 6; float weight = 7; float bmi = 8; - float run_50m = 9; - float standing_long_jump = 10; - float sit_and_reach = 11; - float run_800m = 12; - float run_1000m = 13; - int32 sit_ups = 14; - int32 pull_ups = 15; - int32 lung_capacity = 16; - float total_score = 17; + float run50m = 9; + float standingLongJump = 10; + float sitAndReach = 11; + float run800m = 12; + float run1000m = 13; + int32 sitUps = 14; + int32 pullUps = 15; + int32 lungCapacity = 16; + float totalScore = 17; }同样的命名修改也应应用于
UpdateFitnessScoreRequest、DeleteFitnessScoreRequest和FitnessScore消息。
871-917:StoreFitnessScoreRequest和UpdateFitnessScoreRequest字段完全相同,存在代码重复。两个请求消息的字段定义完全一致,违反 DRY 原则。可以考虑:
- 直接复用
FitnessScore消息作为请求体- 或者如果
UpdateFitnessScore需要支持部分更新,考虑使用google.protobuf.FieldMask♻️ 建议复用 FitnessScore
-// StoreFitnessScoreRequest 新增或更新体测成绩请求 -message StoreFitnessScoreRequest { - string staff_id = 1; - // ... 省略重复字段 -} +// StoreFitnessScoreRequest 新增或更新体测成绩请求 +message StoreFitnessScoreRequest { + FitnessScore fitness_score = 1; +} -// UpdateFitnessScoreRequest 更新体测成绩请求 -message UpdateFitnessScoreRequest { - string staff_id = 1; - // ... 省略重复字段 -} +// UpdateFitnessScoreRequest 更新体测成绩请求 +message UpdateFitnessScoreRequest { + FitnessScore fitness_score = 1; + google.protobuf.FieldMask update_mask = 2; // 可选:指定要更新的字段 +}
926-931: 删除请求的关键字段应明确标注为必填。
DeleteFitnessScoreRequest中的staff_id、school_year、semester是定位记录的关键字段,建议在注释中明确说明这些字段为必填,便于 API 使用者理解。♻️ 添加必填说明
// DeleteFitnessScoreRequest 删除体测成绩请求 message DeleteFitnessScoreRequest { - string staff_id = 1; - string school_year = 2; - int32 semester = 3; + // 学工号(必填) + string staff_id = 1; + // 学年(必填) + string school_year = 2; + // 学期(必填) + int32 semester = 3; }docs/swagger/campusapis/staff/v1/campus.swagger.json (1)
62-200: POST 和 PATCH 操作缺少consumes字段定义。根据 OpenAPI 2.0 规范,包含请求体的操作(POST、PATCH、PUT)应定义
consumes字段。虽然文件顶层已定义全局consumes: ["application/json"],但静态分析工具建议在操作级别也明确声明,以提高 API 文档的清晰度。由于这是自动生成的文件,可以考虑配置 gRPC-gateway 或 protoc-gen-openapiv2 插件来添加此字段。
| "/fitness/score": { | ||
| "delete": { | ||
| "summary": "删除体测成绩", | ||
| "operationId": "CampusService_DeleteFitnessScore2", | ||
| "responses": { | ||
| "200": { | ||
| "description": "A successful response.", | ||
| "schema": { | ||
| "$ref": "#/definitions/v1DeleteFitnessScoreResponse" | ||
| } | ||
| }, | ||
| "default": { | ||
| "description": "An unexpected error response.", | ||
| "schema": { | ||
| "$ref": "#/definitions/rpcStatus" | ||
| } | ||
| } | ||
| }, | ||
| "parameters": [ | ||
| { | ||
| "name": "staffId", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "string" | ||
| }, | ||
| { | ||
| "name": "schoolYear", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "string" | ||
| }, | ||
| { | ||
| "name": "semester", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "integer", | ||
| "format": "int32" | ||
| } | ||
| ], | ||
| "tags": [ | ||
| "CampusService" | ||
| ] | ||
| }, | ||
| "post": { | ||
| "summary": "新增或更新体测成绩", | ||
| "operationId": "CampusService_StoreFitnessScore2", | ||
| "responses": { | ||
| "200": { | ||
| "description": "A successful response.", | ||
| "schema": { | ||
| "$ref": "#/definitions/v1StoreFitnessScoreResponse" | ||
| } | ||
| }, | ||
| "default": { | ||
| "description": "An unexpected error response.", | ||
| "schema": { | ||
| "$ref": "#/definitions/rpcStatus" | ||
| } | ||
| } | ||
| }, | ||
| "parameters": [ | ||
| { | ||
| "name": "staffId", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "string" | ||
| }, | ||
| { | ||
| "name": "schoolYear", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "string" | ||
| }, | ||
| { | ||
| "name": "semester", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "integer", | ||
| "format": "int32" | ||
| }, | ||
| { | ||
| "name": "gender", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "string" | ||
| }, | ||
| { | ||
| "name": "grade", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "integer", | ||
| "format": "int32" | ||
| }, | ||
| { | ||
| "name": "height", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "number", | ||
| "format": "float" | ||
| }, | ||
| { | ||
| "name": "weight", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "number", | ||
| "format": "float" | ||
| }, | ||
| { | ||
| "name": "bmi", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "number", | ||
| "format": "float" | ||
| }, | ||
| { | ||
| "name": "run50m", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "number", | ||
| "format": "float" | ||
| }, | ||
| { | ||
| "name": "standingLongJump", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "number", | ||
| "format": "float" | ||
| }, | ||
| { | ||
| "name": "sitAndReach", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "number", | ||
| "format": "float" | ||
| }, | ||
| { | ||
| "name": "run800m", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "number", | ||
| "format": "float" | ||
| }, | ||
| { | ||
| "name": "run1000m", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "number", | ||
| "format": "float" | ||
| }, | ||
| { | ||
| "name": "sitUps", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "integer", | ||
| "format": "int32" | ||
| }, | ||
| { | ||
| "name": "pullUps", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "integer", | ||
| "format": "int32" | ||
| }, | ||
| { | ||
| "name": "lungCapacity", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "integer", | ||
| "format": "int32" | ||
| }, | ||
| { | ||
| "name": "totalScore", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "number", | ||
| "format": "float" | ||
| } | ||
| ], | ||
| "tags": [ | ||
| "CampusService" | ||
| ] | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
find . -name "campus.proto" -path "*/campusapis/staff/v1/*" | head -5Repository: hduhelp/api_open_sdk
Length of output: 98
🏁 Script executed:
cat ./campusapis/staff/v1/campus.proto | grep -A 20 "DeleteFitnessScore\|StoreFitnessScore"Repository: hduhelp/api_open_sdk
Length of output: 2597
🏁 Script executed:
# Verify the swagger.json reflects the proto misconfiguration
grep -n "\"in\": \"query\"" docs/swagger/campusapis/staff/v1/campus.swagger.json | head -5
grep -n "\"in\": \"body\"" docs/swagger/campusapis/staff/v1/campus.swagger.json | head -5Repository: hduhelp/api_open_sdk
Length of output: 273
/fitness/score 的 POST/PATCH 操作需要修复 proto 配置中的 body 声明。
/fitness/score 的 POST 和 PATCH 操作使用 query 参数传递所有字段,而 /staff/v1/fitness/score 使用 body 传递。根本原因在于 proto 文件中,这两个操作的 additional_bindings 缺少 body: "*" 声明。
在 campusapis/staff/v1/campus.proto 中修改:
rpc StoreFitnessScore(StoreFitnessScoreRequest) returns (StoreFitnessScoreResponse) {
option (google.api.http) = {
post: "/staff/v1/fitness/score"
body: "*"
additional_bindings {
post: "/fitness/score"
body: "*" // 添加此行
}
};
}
rpc UpdateFitnessScore(UpdateFitnessScoreRequest) returns (UpdateFitnessScoreResponse) {
option (google.api.http) = {
patch: "/staff/v1/fitness/score"
body: "*"
additional_bindings {
patch: "/fitness/score"
body: "*" // 添加此行
}
};
}
使用 query 参数传递 POST/PATCH 请求会导致敏感数据暴露在 URL 中(日志、浏览器历史等),违反 REST 最佳实践,且两个端点行为不一致。
🧰 Tools
🪛 Checkov (3.2.334)
[medium] 62-199: Ensure that operation objects have 'consumes' field defined for PUT, POST and PATCH operations - version 2.0 files
(CKV_OPENAPI_17)
🤖 Prompt for AI Agents
In `@docs/swagger/campusapis/staff/v1/campus.swagger.json` around lines 19 - 200,
The POST/PATCH endpoints for /fitness/score are using query params because the
proto additional_bindings for StoreFitnessScore and UpdateFitnessScore lack a
body declaration; open the rpc definitions
StoreFitnessScore(StoreFitnessScoreRequest) and
UpdateFitnessScore(UpdateFitnessScoreRequest) in campus.proto and add body: "*"
inside each additional_bindings block that binds to "/fitness/score" (so the
additional_bindings post/patch entries include body: "*"), then regenerate the
swagger so those endpoints accept the request body instead of query parameters.
| "parameters": [ | ||
| { | ||
| "name": "staffId", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "string" | ||
| }, | ||
| { | ||
| "name": "schoolYear", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "string" | ||
| }, | ||
| { | ||
| "name": "semester", | ||
| "in": "query", | ||
| "required": false, | ||
| "type": "integer", | ||
| "format": "int32" | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
删除操作的关键参数应标记为必填。
staffId、schoolYear、semester 是定位要删除记录的必要参数,但当前都标记为 "required": false。这可能导致调用者遗漏必要参数,造成意外行为。
由于这是自动生成的 Swagger 文件,应在 proto 定义中通过注释或 proto 选项来控制必填性,或在服务实现中增加校验。
🤖 Prompt for AI Agents
In `@docs/swagger/campusapis/staff/v1/campus.swagger.json` around lines 37 - 56,
The DELETE operation currently has its identifying query parameters marked as
optional; update the parameter definitions for "staffId", "schoolYear", and
"semester" to "required": true in the Swagger spec so callers must supply them,
or preferably add field behavior annotations in the proto (e.g.,
google.api.field_behavior = REQUIRED on those fields) and regenerate the
swagger; also add server-side validation in the delete handler to enforce
presence/validity of staffId/schoolYear/semester before performing deletion.
Summary by CodeRabbit
发布说明
✏️ Tip: You can customize this high-level summary in your review settings.