diff --git a/pkg/base/context/login_data.go b/pkg/base/context/login_data.go index e8d03b4eb..bdb772237 100644 --- a/pkg/base/context/login_data.go +++ b/pkg/base/context/login_data.go @@ -62,8 +62,12 @@ func ExtractIDFromLoginData(data *model.LoginData) string { } // ExtractIDFromIdentifier 从 Identifier 中提取学号 -// 本科生:从id截取 9 位 如: 20241025133150102401339 -// 研究生:id直接是stuId可能是 9 或 10 位 +// 研究生:id直接是stuId,以 00000 为前缀(可能是 9 或 10 位) +// 本科生:identifier 末尾为学号,按入学年份判断是 9 位还是 10 位 +// 2026年开始本科生学号由9位变到10位 +// 本科生identifier规则:请求时间 yyyymmdd + hhmmss + 学号,长度不定 +// 比如请求时间在2026年8月5日,开头就是202685,12月17日就是20261217 +// 时间也是一样,24小时制,当日1时50分7秒就是1507,10时0分0秒就是1000,12时37分59秒就是123759 func ExtractIDFromIdentifier(id string) string { if len(id) < constants.StudentIDLength { return "" @@ -75,5 +79,5 @@ func ExtractIDFromIdentifier(id string) string { } // 本科生 - return id[len(id)-constants.StudentIDLength:] + return utils.RemoveUndergraduatePrefix(id) } diff --git a/pkg/base/context/login_data_test.go b/pkg/base/context/login_data_test.go new file mode 100644 index 000000000..281d2c365 --- /dev/null +++ b/pkg/base/context/login_data_test.go @@ -0,0 +1,68 @@ +/* +Copyright 2024 The west2-online Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package context + +import "testing" + +func TestExtractIDFromIdentifier(t *testing.T) { + tests := []struct { + name string + id string + want string + }{ + { + name: "研究生-9位学号", + // 00000 + 102301001 + id: "00000102301001", + want: "102301001", + }, + { + name: "研究生-10位学号", + // 00000 + 1026012345 + id: "000001026012345", + want: "1026012345", + }, + { + name: "本科生-9位学号", + id: "20268514814222200311", + want: "222200311", + }, + { + name: "本科生-10位学号", + id: "202685148140102612345", + want: "0102612345", + }, + { + name: "过短", + id: "123", + want: "", + }, + { + name: "空", + id: "", + want: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := ExtractIDFromIdentifier(tt.id); got != tt.want { + t.Errorf("ExtractIDFromIdentifier() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/constants/jwch.go b/pkg/constants/jwch.go index 636954bd9..917b70584 100644 --- a/pkg/constants/jwch.go +++ b/pkg/constants/jwch.go @@ -18,8 +18,13 @@ package constants const ( MaxRetries = 5 // 最大重试次数 - StudentIDLength = 9 // 学号的长度,用于截取处学号 + StudentIDLength = 9 // 本科基础学号长度(2026年前入学为9位),也是从 identifier 提取时的最小长度 InitialDelay = 1 * ONE_SECOND // 初始等待时间 YjsTermLen = 6 // 研究生学期长度 JwchTermLen = 6 + + // 2026年(含)起入学的新生学号由9位变为10位。 + // 学号第3-4位为入学年份(如 22/25/26),年份 >= StudentIDYearThreshold 时为10位新学号。 + StudentIDLengthNew = 10 + StudentIDYearThreshold = 26 ) diff --git a/pkg/utils/id.go b/pkg/utils/id.go index d8e18636f..1ed83d7e9 100644 --- a/pkg/utils/id.go +++ b/pkg/utils/id.go @@ -17,7 +17,10 @@ limitations under the License. package utils import ( + "strconv" "strings" + + "github.com/west2-online/fzuhelper-server/pkg/constants" ) // IsGraduate 根据 identifier 判断是否是研究生 @@ -35,7 +38,19 @@ func MarkGraduate(id string) string { return "00000" + id } -// RemoveUndergraduatePrefix 去除本科生的学号前缀 +// RemoveUndergraduatePrefix 去除本科生的学号前缀,返回真实学号。 +// 学号格式为 xxyyxxxxx(9位,2026年前入学)或 xxxyyxxxxx(10位,2026年起入学), +// 其中第3-4位 yy 为入学年份,通过年份判断学号位数。 func RemoveUndergraduatePrefix(id string) string { - return id[len(id)-9:] + if len(id) < constants.StudentIDLength { + return "" + } + // 先取后9位,其第3-4位为入学年份 + last9 := id[len(id)-constants.StudentIDLength:] + // 年份 >= 26(2026年起入学)为10位新学号,取后10位 + year, err := strconv.Atoi(last9[2:4]) + if err == nil && len(id) >= constants.StudentIDLengthNew && year >= constants.StudentIDYearThreshold { + return id[len(id)-constants.StudentIDLengthNew:] + } + return last9 } diff --git a/pkg/utils/id_test.go b/pkg/utils/id_test.go new file mode 100644 index 000000000..f4c217cf8 --- /dev/null +++ b/pkg/utils/id_test.go @@ -0,0 +1,69 @@ +/* +Copyright 2024 The west2-online Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package utils + +import "testing" + +func TestRemoveUndergraduatePrefix(t *testing.T) { + tests := []struct { + name string + id string + want string + }{ + { + name: "9位学号-2022年入学", + // 后9位 222200311,第3-4位 22 < 26 + id: "20268514814222200311", + want: "222200311", + }, + { + name: "9位学号-2025年入学", + // 后9位 102512345,第3-4位 25 < 26 + id: "20268514814102512345", + want: "102512345", + }, + { + name: "10位学号-2026年入学", + // 后9位 026012345,第3-4位 60 >= 26,取后10位 + id: "202685148141026012345", + want: "1026012345", + }, + { + name: "identifier即学号-9位", + id: "222200311", + want: "222200311", + }, + { + name: "过短", + id: "12345678", + want: "", + }, + { + name: "空", + id: "", + want: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := RemoveUndergraduatePrefix(tt.id); got != tt.want { + t.Errorf("RemoveUndergraduatePrefix() = %v, want %v", got, tt.want) + } + }) + } +}