diff --git a/server/skillhub-app/src/main/java/com/iflytek/skillhub/dto/UpdateProfileRequest.java b/server/skillhub-app/src/main/java/com/iflytek/skillhub/dto/UpdateProfileRequest.java
index 3f264b02..b9aed821 100644
--- a/server/skillhub-app/src/main/java/com/iflytek/skillhub/dto/UpdateProfileRequest.java
+++ b/server/skillhub-app/src/main/java/com/iflytek/skillhub/dto/UpdateProfileRequest.java
@@ -12,14 +12,14 @@ import jakarta.validation.constraints.Size;
*
Validation rules for displayName:
*
* - Length: 2–32 characters (after trim)
- * - Allowed characters: Chinese, English, digits, underscore, hyphen
+ * - Allowed characters: Chinese, English, digits, spaces, underscore, hyphen
*
*
* @param displayName new display name (nullable — omit to leave unchanged)
*/
public record UpdateProfileRequest(
@Size(min = 2, max = 32, message = "error.profile.displayName.length")
- @Pattern(regexp = "^[\\u4e00-\\u9fa5a-zA-Z0-9_-]+$",
+ @Pattern(regexp = "^[\\u4e00-\\u9fa5a-zA-Z0-9_ -]+$",
message = "error.profile.displayName.pattern")
String displayName
) {
diff --git a/server/skillhub-app/src/main/resources/messages.properties b/server/skillhub-app/src/main/resources/messages.properties
index 7467829e..1ecfbac6 100644
--- a/server/skillhub-app/src/main/resources/messages.properties
+++ b/server/skillhub-app/src/main/resources/messages.properties
@@ -127,8 +127,7 @@ error.skill.approve.nameConflict=Cannot approve: a published skill with name ''{
# Profile update
error.profile.displayName.length=Display name must be between 2 and 32 characters
-error.profile.displayName.pattern=Display name can only contain Chinese characters, English letters, numbers, underscores, and hyphens
+error.profile.displayName.pattern=Display name can only contain Chinese characters, English letters, numbers, spaces, underscores, and hyphens
error.profile.noChanges=At least one field must be provided
response.profile.updated=Profile updated successfully
response.profile.pendingReview=Profile changes submitted for review
-
diff --git a/server/skillhub-app/src/main/resources/messages_zh.properties b/server/skillhub-app/src/main/resources/messages_zh.properties
index 5075d0ae..c09516be 100644
--- a/server/skillhub-app/src/main/resources/messages_zh.properties
+++ b/server/skillhub-app/src/main/resources/messages_zh.properties
@@ -127,8 +127,7 @@ error.skill.approve.nameConflict=无法通过审核:该命名空间下已存
# 用户资料修改
error.profile.displayName.length=昵称长度需在 2-32 个字符之间
-error.profile.displayName.pattern=昵称仅允许中文、英文、数字、下划线和连字符
+error.profile.displayName.pattern=昵称仅允许中文、英文、数字、空格、下划线和连字符
error.profile.noChanges=至少需要提供一个修改字段
response.profile.updated=资料已更新
response.profile.pendingReview=资料变更已提交审核
-
diff --git a/server/skillhub-app/src/test/java/com/iflytek/skillhub/controller/UserProfileControllerTest.java b/server/skillhub-app/src/test/java/com/iflytek/skillhub/controller/UserProfileControllerTest.java
index fcd240df..b4c25934 100644
--- a/server/skillhub-app/src/test/java/com/iflytek/skillhub/controller/UserProfileControllerTest.java
+++ b/server/skillhub-app/src/test/java/com/iflytek/skillhub/controller/UserProfileControllerTest.java
@@ -135,6 +135,25 @@ class UserProfileControllerTest {
.andExpect(jsonPath("$.data.status").value("APPLIED"));
}
+ @Test
+ void updateProfile_displayNameWithSpaces_shouldReturn200() throws Exception {
+ var principal = testPrincipal();
+ var user = new UserAccount("user-1", "OldName", "user@example.com", "https://example.com/avatar.png");
+
+ given(userAccountRepository.findById("user-1")).willReturn(Optional.of(user));
+ given(namespaceMemberRepository.findByUserId("user-1")).willReturn(List.of());
+ given(userRoleBindingRepository.findByUserId("user-1")).willReturn(List.of());
+
+ mockMvc.perform(patch("/api/v1/user/profile")
+ .with(authentication(testAuth(principal)))
+ .with(csrf())
+ .contentType(MediaType.APPLICATION_JSON)
+ .content("{\"displayName\":\"New Name\"}"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.code").value(0))
+ .andExpect(jsonPath("$.data.status").value("APPLIED"));
+ }
+
// ===== AC-E-001: Display name too short =====
@Test
diff --git a/web/src/i18n/locales/en.json b/web/src/i18n/locales/en.json
index 5b6c6336..39f4d5e2 100644
--- a/web/src/i18n/locales/en.json
+++ b/web/src/i18n/locales/en.json
@@ -525,7 +525,7 @@
"defaultError": "Failed to update profile. Please try again.",
"validation": {
"length": "Display name must be 2-32 characters.",
- "pattern": "Display name can only contain Chinese, English, digits, underscores, and hyphens."
+ "pattern": "Display name can only contain Chinese, English, digits, spaces, underscores, and hyphens."
}
},
"security": {
diff --git a/web/src/i18n/locales/zh.json b/web/src/i18n/locales/zh.json
index 7a6d7a3e..01651211 100644
--- a/web/src/i18n/locales/zh.json
+++ b/web/src/i18n/locales/zh.json
@@ -525,7 +525,7 @@
"defaultError": "修改失败,请稍后重试。",
"validation": {
"length": "昵称长度需为 2-32 个字符。",
- "pattern": "昵称只能包含中文、英文、数字、下划线和连字符。"
+ "pattern": "昵称只能包含中文、英文、数字、空格、下划线和连字符。"
}
},
"security": {
diff --git a/web/src/pages/settings/profile.tsx b/web/src/pages/settings/profile.tsx
index ce9327ff..b54f235a 100644
--- a/web/src/pages/settings/profile.tsx
+++ b/web/src/pages/settings/profile.tsx
@@ -9,8 +9,8 @@ import { Button } from '@/shared/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/shared/ui/card'
import { Input } from '@/shared/ui/input'
-/** Regex matching allowed display name characters: Chinese, English, digits, underscore, hyphen. */
-const DISPLAY_NAME_PATTERN = /^[\u4e00-\u9fa5a-zA-Z0-9_-]+$/
+/** Regex matching allowed display name characters: Chinese, English, digits, spaces, underscore, hyphen. */
+const DISPLAY_NAME_PATTERN = /^[\u4e00-\u9fa5a-zA-Z0-9_ -]+$/
export function ProfileSettingsPage() {
const { t } = useTranslation()