diff --git a/backend/schemas/user.py b/backend/schemas/user.py index 733789f..e06b176 100644 --- a/backend/schemas/user.py +++ b/backend/schemas/user.py @@ -12,6 +12,7 @@ class UserCreate(UserBase): """创建用户 Schema(管理员手动创建,只需要别名)""" role: Optional[str] = Field("user", description="角色: user/admin") email: Optional[EmailStr] = Field(None, description="邮箱地址") + password: Optional[str] = Field(None, min_length=6, description="初始密码(可选)") is_approved: Optional[bool] = Field(True, description="是否已审批(默认已审批)") diff --git a/backend/services/user_service.py b/backend/services/user_service.py index bd6623a..97f47f7 100644 --- a/backend/services/user_service.py +++ b/backend/services/user_service.py @@ -32,7 +32,7 @@ class UserService: 创建用户(管理员手动创建) Args: - user_data: 用户创建数据(只需要 alias 和 role) + user_data: 用户创建数据(包括 alias, role, email, password 等) db: 数据库会话 Returns: @@ -47,17 +47,24 @@ class UserService: user = User( jwt_sub=None, # NULL 表示未绑定 QQ alias=user_data.alias, + email=user_data.email, role=user_data.role or "user", is_approved=user_data.is_approved if user_data.is_approved is not None else True, # 使用请求中的值,默认已审批 jwt_exp="0", authorization=None, ) + # 如果提供了密码,则设置密码 + if user_data.password: + import bcrypt + password_hash = bcrypt.hashpw(user_data.password.encode('utf-8'), bcrypt.gensalt()) + setattr(user, 'password_hash', password_hash.decode('utf-8')) + db.add(user) db.commit() db.refresh(user) - logger.info(f"管理员创建用户成功: {user.alias} (ID: {user.id}, 角色: {user.role})") + logger.info(f"管理员创建用户成功: {user.alias} (ID: {user.id}, 角色: {user.role}, 密码: {'已设置' if user_data.password else '未设置'})") return user @staticmethod diff --git a/frontend/src/views/admin/UsersView.vue b/frontend/src/views/admin/UsersView.vue index 5658664..882d287 100644 --- a/frontend/src/views/admin/UsersView.vue +++ b/frontend/src/views/admin/UsersView.vue @@ -442,10 +442,36 @@ const handleSubmit = async () => { } if (dialogMode.value === 'create') { - await userStore.createUser(formData.value); + // 创建用户时,只发送后端 UserCreate schema 接受的字段 + const createData = { + alias: formData.value.alias, + role: formData.value.role, + is_approved: formData.value.is_approved, + }; + // 如果有邮箱,添加邮箱字段(空字符串转为 null) + if (formData.value.email && formData.value.email.trim()) { + createData.email = formData.value.email.trim(); + } + // 如果有密码,添加密码字段 + if (formData.value.password && formData.value.password.trim()) { + createData.password = formData.value.password.trim(); + } + await userStore.createUser(createData); message.success('创建成功'); } else { - await userStore.updateUser(formData.value.id, formData.value); + // 编辑用户时,处理空字符串字段 + const updateData = { + ...formData.value, + // 将空字符串的邮箱转为 null + email: + formData.value.email && formData.value.email.trim() ? formData.value.email.trim() : null, + // 将空字符串的密码转为 null + password: + formData.value.password && formData.value.password.trim() + ? formData.value.password.trim() + : null, + }; + await userStore.updateUser(formData.value.id, updateData); message.success('更新成功'); }