From dfb489102296eaec8489d6e0cc7305ea1a9928fc Mon Sep 17 00:00:00 2001 From: HenryDu8133 <813367384@qq.com> Date: Wed, 30 Sep 2026 22:02:14 +0800 Subject: [PATCH] =?UTF-8?q?fix(users):=20=E5=8F=AA=E6=A0=A1=E9=AA=8C"?= =?UTF-8?q?=E7=9C=9F=E7=9A=84=E6=94=B9=E8=BF=87"=E7=9A=84=E5=A7=93?= =?UTF-8?q?=E5=90=8D/=E8=B4=A6=E5=8F=B7=E5=90=8D=EF=BC=8C=E4=BF=AE?= =?UTF-8?q?=E5=9B=9E"=E7=AE=A1=E7=90=86=E5=91=98=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E5=85=B6=E4=BB=96=E7=94=A8=E6=88=B7"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 站长反馈:管理员无法编辑其他用户信息了。 根因:「姓名/账号名必须纯中文」的校验是**每次编辑都重新做一遍**的, 所以历史账号(早期用拼音/英文建的、名字里带「·」或空格的)连"改个年级" 都会被这条规则拦死 —— 管理员等于没法维护这些账号。admin 账号之前也是同一个毛病。 改成与服务端同一口径的"只校验改动过的字段": - 没改动 → 不校验(历史数据原样保留,不强迫改名); - 改了 → 必须满足规则(纯中文;admin 账号的姓名例外); - 主动把中文名改成拼音/带空格 → 仍然拦。 初始管理员(ID=1)的规则不变:登录名必须保持 admin、角色锁死、密码不在这里改。 (对应的小程序端同样改成"只校验改动字段":编辑时记下原始姓名/账号名, 提交时比对;新增时两个字段都校验。) --- server/api/admin/users/[id].put.ts | 41 ++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/server/api/admin/users/[id].put.ts b/server/api/admin/users/[id].put.ts index 2f5884c..9825c1b 100644 --- a/server/api/admin/users/[id].put.ts +++ b/server/api/admin/users/[id].put.ts @@ -29,14 +29,6 @@ export default defineEventHandler(async (event) => { }) } - // 账号名必须是纯中文;**admin 账号例外**(以前没有例外,连它自己都编辑不了) - if (!isValidPersonName(name, username) || !isValidUsername(username)) { - throw createError({ - statusCode: 400, - statusMessage: NAME_RULE_MESSAGE + ';' + USERNAME_RULE_MESSAGE - }) - } - // 检查用户是否存在 const existingUser = await db .select() @@ -55,6 +47,35 @@ export default defineEventHandler(async (event) => { const currentLevel = getRoleLevel(user.role) const targetLevel = getRoleLevel(targetUser.role) + /* + * 姓名 / 账号名的中文规则:**只校验"这次真的改了"的字段**。 + * + * 站长反馈「管理员无法编辑其他用户信息了」——根因就在这里: + * 原来(以及我上一版照搬的写法)是"每次编辑都重新校验姓名和账号名", + * 于是**历史账号**(早期用拼音/英文建的、或者名字里带「·」「空格」的) + * 连"改个年级"都会撞「必须纯中文」而被拦死,管理员等于没法维护这些账号。 + * 现在的口径: + * · 没改动 → 不校验(历史数据**原样保留**,不强迫改名); + * · 改了 → 必须满足规则(纯中文;admin 账号例外)。 + */ + const nextUsername = String(username || '').trim() + const nextName = String(name || '').trim() + const usernameChanged = nextUsername !== String(targetUser.username || '') + const nameChanged = nextName !== String(targetUser.name || '') + + if (usernameChanged && !isValidUsername(nextUsername)) { + throw createError({ + statusCode: 400, + statusMessage: USERNAME_RULE_MESSAGE + }) + } + if (nameChanged && !isValidPersonName(nextName, nextUsername)) { + throw createError({ + statusCode: 400, + statusMessage: NAME_RULE_MESSAGE + }) + } + /* * 系统初始超级管理员(ID=1,登录名 admin)的处理 —— 第 90 轮按站长要求放宽。 * @@ -67,8 +88,8 @@ export default defineEventHandler(async (event) => { * · 锁死:密码不在这里改(避免被其它管理员顺手重置)。 */ if (targetUser.id === 1) { - const nextUsername = String(username || '').trim() - if (nextUsername && nextUsername !== targetUser.username) { + // 登录名必须还是 admin(usernameChanged 已在上面的中文规则里判过"有没有改") + if (usernameChanged) { throw createError({ statusCode: 400, statusMessage: '初始超级管理员的登录名必须保持 admin(应急登录通道,改了就无法用它登录)'