1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
| @RestController
@RequestMapping("/api/v1/users")
@Tag(name = "User Management", description = "用戶管理相關 API")
@SecurityRequirement(name = "bearerAuth")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping
@Operation(
summary = "獲取用戶列表",
description = "分頁查詢用戶資訊,支援多種過濾條件",
tags = {"User Management"}
)
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "成功獲取用戶列表",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = PagedUserResponse.class),
examples = @ExampleObject(
name = "用戶列表範例",
value = """
{
"content": [
{
"id": 1,
"username": "john_doe",
"email": "john@example.com",
"firstName": "John",
"lastName": "Doe",
"createdAt": "2023-01-15T10:30:00Z"
}
],
"pageable": {
"page": 0,
"size": 20,
"totalElements": 1,
"totalPages": 1
}
}
"""
)
)
),
@ApiResponse(
responseCode = "400",
description = "請求參數錯誤",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class)
)
),
@ApiResponse(
responseCode = "401",
description = "未授權訪問",
content = @Content(schema = @Schema(implementation = ErrorResponse.class))
),
@ApiResponse(
responseCode = "403",
description = "權限不足",
content = @Content(schema = @Schema(implementation = ErrorResponse.class))
)
})
public ResponseEntity<Page<UserResponse>> getUsers(
@Parameter(
description = "頁碼(從 0 開始)",
example = "0",
schema = @Schema(minimum = "0", defaultValue = "0")
)
@RequestParam(defaultValue = "0")
@Min(0) int page,
@Parameter(
description = "每頁大小",
example = "20",
schema = @Schema(minimum = "1", maximum = "100", defaultValue = "20")
)
@RequestParam(defaultValue = "20")
@Min(1) @Max(100) int size,
@Parameter(
description = "排序欄位,格式:field,direction",
example = "createdAt,desc",
array = @ArraySchema(schema = @Schema(type = "string"))
)
@RequestParam(defaultValue = "createdAt,desc") String[] sort,
@Parameter(
description = "用戶名搜尋關鍵字",
example = "john"
)
@RequestParam(required = false) String username,
@Parameter(
description = "郵箱搜尋關鍵字",
example = "example.com"
)
@RequestParam(required = false) String email,
@Parameter(
description = "用戶狀態過濾",
schema = @Schema(allowableValues = {"ACTIVE", "INACTIVE", "SUSPENDED"})
)
@RequestParam(required = false) UserStatus status
) {
UserSearchCriteria criteria = UserSearchCriteria.builder()
.username(username)
.email(email)
.status(status)
.build();
Pageable pageable = createPageable(page, size, sort);
Page<UserResponse> users = userService.findUsers(criteria, pageable);
return ResponseEntity.ok(users);
}
@GetMapping("/{id}")
@Operation(
summary = "根據 ID 獲取用戶",
description = "根據用戶 ID 獲取詳細資訊"
)
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "成功獲取用戶資訊",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = UserDetailResponse.class)
)
),
@ApiResponse(responseCode = "404", description = "用戶不存在")
})
public ResponseEntity<UserDetailResponse> getUserById(
@Parameter(
description = "用戶 ID",
required = true,
example = "123"
)
@PathVariable
@Positive Long id
) {
UserDetailResponse user = userService.findDetailById(id);
return ResponseEntity.ok(user);
}
@PostMapping
@Operation(
summary = "創建新用戶",
description = "創建新的用戶帳戶,郵箱必須唯一"
)
@ApiResponses(value = {
@ApiResponse(
responseCode = "201",
description = "用戶創建成功",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = UserResponse.class)
)
),
@ApiResponse(
responseCode = "400",
description = "請求資料驗證失敗",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ValidationErrorResponse.class)
)
),
@ApiResponse(
responseCode = "409",
description = "郵箱已存在"
)
})
public ResponseEntity<UserResponse> createUser(
@io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "用戶創建請求",
required = true,
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = CreateUserRequest.class),
examples = @ExampleObject(
name = "用戶創建範例",
value = """
{
"username": "john_doe",
"email": "john@example.com",
"firstName": "John",
"lastName": "Doe",
"password": "SecurePassword123!"
}
"""
)
)
)
@RequestBody @Valid CreateUserRequest request
) {
UserResponse user = userService.createUser(request);
URI location = URI.create("/api/v1/users/" + user.getId());
return ResponseEntity.created(location).body(user);
}
@PutMapping("/{id}")
@Operation(
summary = "更新用戶資訊",
description = "更新指定用戶的基本資訊"
)
public ResponseEntity<UserResponse> updateUser(
@PathVariable @Positive Long id,
@RequestBody @Valid UpdateUserRequest request
) {
UserResponse user = userService.updateUser(id, request);
return ResponseEntity.ok(user);
}
@DeleteMapping("/{id}")
@Operation(
summary = "刪除用戶",
description = "軟刪除指定用戶(標記為已刪除狀態)"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "刪除成功"),
@ApiResponse(responseCode = "404", description = "用戶不存在"),
@ApiResponse(responseCode = "409", description = "用戶有關聯資料,無法刪除")
})
public ResponseEntity<Void> deleteUser(
@PathVariable @Positive Long id
) {
userService.deleteUser(id);
return ResponseEntity.noContent().build();
}
@PostMapping("/{id}/avatar")
@Operation(
summary = "上傳用戶頭像",
description = "上傳用戶頭像圖片,支援 JPG、PNG 格式"
)
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "頭像上傳成功",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = UploadResponse.class)
)
),
@ApiResponse(responseCode = "400", description = "檔案格式不支援"),
@ApiResponse(responseCode = "413", description = "檔案大小超出限制")
})
public ResponseEntity<UploadResponse> uploadAvatar(
@PathVariable @Positive Long id,
@Parameter(
description = "頭像圖片檔案",
required = true,
content = @Content(mediaType = "multipart/form-data")
)
@RequestParam("file") MultipartFile file
) {
UploadResponse response = userService.uploadAvatar(id, file);
return ResponseEntity.ok(response);
}
}
|
留言討論