fix: add server-side sorting to user list, prevent client-side sort on paged data (#6194)

* fix: add server-side sorting to user list, prevent client-side sort on paged data

The user management table applied client-side sorting to the current
page slice while pagination was handled server-side, causing ID-asc
views to show pages out of order (e.g. 23-42, 3-22, 1-2).

Backend: add sort_by/sort_order query params to GetAllUsers and
SearchUsers with a column whitelist for safe ORDER BY generation.
Frontend: pass sorting state to the API and reset to page 1 on sort
change. Generic useDataTable hook now disables client-side sorted row
model and sort UI for tables with manual pagination but no server-side
sort handler.

* fix: add id tie-breaker to non-unique sort columns, remove side effect from state updater

Append secondary ORDER BY id DESC when sorting by non-unique columns
(quota, created_at, etc.) to prevent row duplication/skipping across
OFFSET pages.

Move onPaginationChange out of setSorting updater to avoid side effects
inside a pure function (React Strict Mode double-invocation safety).
This commit is contained in:
DawnMoon1542
2026-07-17 19:36:44 +08:00
committed by GitHub
parent a63364d156
commit 506e41c116
8 changed files with 207 additions and 11 deletions
+4 -2
View File
@@ -308,7 +308,8 @@ func Register(c *gin.Context) {
func GetAllUsers(c *gin.Context) {
pageInfo := common.GetPageQuery(c)
users, total, err := model.GetAllUsers(pageInfo)
sortOptions := model.NewUserSortOptions(c.Query("sort_by"), c.Query("sort_order"))
users, total, err := model.GetAllUsers(pageInfo, sortOptions)
if err != nil {
common.ApiError(c, err)
return
@@ -337,7 +338,8 @@ func SearchUsers(c *gin.Context) {
}
}
pageInfo := common.GetPageQuery(c)
users, total, err := model.SearchUsers(keyword, group, role, status, pageInfo.GetStartIdx(), pageInfo.GetPageSize())
sortOptions := model.NewUserSortOptions(c.Query("sort_by"), c.Query("sort_order"))
users, total, err := model.SearchUsers(keyword, group, role, status, pageInfo.GetStartIdx(), pageInfo.GetPageSize(), sortOptions)
if err != nil {
common.ApiError(c, err)
return