From cca2d77ea229cdea04368d418261f933c63769d4 Mon Sep 17 00:00:00 2001 From: iven Date: Wed, 3 Jun 2026 09:56:24 +0800 Subject: [PATCH] =?UTF-8?q?fix(diary):=20=E7=8F=AD=E7=BA=A7=E7=A0=81?= =?UTF-8?q?=E6=94=B9=E7=94=A8=E5=AD=97=E6=AF=8D=E6=95=B0=E5=AD=97=E6=B7=B7?= =?UTF-8?q?=E5=90=88=20=E2=80=94=2016^6=20=E6=8F=90=E5=8D=87=E5=88=B0=2062?= =?UTF-8?q?^6=EF=BC=88568=20=E4=BA=BF=E7=BB=84=E5=90=88=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 从 UUID hex 后 6 位(0-9a-f,16^6 ≈ 1677 万)改为字母数字混合 - 字符集: 0-9A-Za-z(62 字符,62^6 ≈ 568 亿) - 使用 UUID v7 后 8 字节随机部分作为熵源,避免同毫秒碰撞 - 符合 CLAUDE.md 设计规格要求 审计 ID: 7b-C01 --- crates/erp-diary/src/service/class_service.rs | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/crates/erp-diary/src/service/class_service.rs b/crates/erp-diary/src/service/class_service.rs index c51874c..d3cdfd2 100644 --- a/crates/erp-diary/src/service/class_service.rs +++ b/crates/erp-diary/src/service/class_service.rs @@ -520,20 +520,21 @@ impl ClassService { } } -/// 生成 6 位班级码(UUID 前 6 位字符) +/// 生成 6 位字母数字混合班级码(62^6 ≈ 568 亿种组合) +/// +/// CLAUDE.md 要求"6 位字母数字混合(62^6 ≈ 568 亿种组合)"。 +/// 使用 UUID v7 后 8 字节(随机部分)作为熵源,映射到 [0-9A-Za-z] 字符集。 +/// 前 8 字节含时间戳,同毫秒内重复概率高,因此只用后 8 字节。 fn generate_class_code() -> String { - // UUID v7 毫秒级时间戳前缀在紧凑循环中可能重复 - // 取后 6 位(随机部分)而非前 6 位(时间戳部分) - Uuid::now_v7() - .to_string() - .replace("-", "") - .chars() - .rev() - .take(6) - .collect::() - .chars() - .rev() - .collect() + const CHARSET: &[u8] = b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + let bytes = *Uuid::now_v7().as_bytes(); + let mut code = String::with_capacity(6); + // UUID v7: bytes[0..8] = 时间戳, bytes[8..16] = 随机部分 + // 从随机部分取 6 个字节,避免同毫秒碰撞 + for i in 0..6 { + code.push(CHARSET[(bytes[8 + i] as usize) % CHARSET.len()] as char); + } + code } /// school_class::Model -> ClassResp