From 014fb7edab02b80c73c5de67f0547251a588114e Mon Sep 17 00:00:00 2001 From: CalciumIon <1808837298@qq.com> Date: Tue, 31 Dec 2024 15:02:59 +0800 Subject: [PATCH] feat: enhance user search functionality with pagination support - Updated SearchUsers function to include pagination parameters (startIdx and num) for improved user search results. - Modified API response structure to return paginated data, including total user count and current page information. - Adjusted UsersTable component to handle pagination and search parameters, ensuring a seamless user experience. - Added internationalization support for new search functionality in the UI. --- controller/user.go | 18 +++++++- model/user.go | 66 ++++++++++++++++++++++-------- web/src/components/UsersTable.js | 70 ++++++++++++++------------------ web/src/i18n/locales/en.json | 4 +- 4 files changed, 97 insertions(+), 61 deletions(-) diff --git a/controller/user.go b/controller/user.go index 4a5db14e..9e1361f4 100644 --- a/controller/user.go +++ b/controller/user.go @@ -274,7 +274,16 @@ func GetAllUsers(c *gin.Context) { func SearchUsers(c *gin.Context) { keyword := c.Query("keyword") group := c.Query("group") - users, err := model.SearchUsers(keyword, group) + p, _ := strconv.Atoi(c.Query("p")) + pageSize, _ := strconv.Atoi(c.Query("page_size")) + if p < 1 { + p = 1 + } + if pageSize < 0 { + pageSize = common.ItemsPerPage + } + startIdx := (p - 1) * pageSize + users, total, err := model.SearchUsers(keyword, group, startIdx, pageSize) if err != nil { c.JSON(http.StatusOK, gin.H{ "success": false, @@ -285,7 +294,12 @@ func SearchUsers(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "success": true, "message": "", - "data": users, + "data": gin.H{ + "items": users, + "total": total, + "page": p, + "page_size": pageSize, + }, }) return } diff --git a/model/user.go b/model/user.go index 08392c04..1b159ba7 100644 --- a/model/user.go +++ b/model/user.go @@ -115,36 +115,66 @@ func GetAllUsers(startIdx int, num int) (users []*User, total int64, err error) return users, total, nil } -func SearchUsers(keyword string, group string) ([]*User, error) { +func SearchUsers(keyword string, group string, startIdx int, num int) ([]*User, int64, error) { var users []*User + var total int64 var err error + // 开始事务 + tx := DB.Begin() + if tx.Error != nil { + return nil, 0, tx.Error + } + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() + + // 构建基础查询 + query := tx.Unscoped().Model(&User{}) + // 尝试将关键字转换为整数ID keywordInt, err := strconv.Atoi(keyword) if err == nil { // 如果转换成功,按照ID和可选的组别搜索用户 - query := DB.Unscoped().Omit("password").Where("id = ?", keywordInt) if group != "" { - query = query.Where(groupCol+" = ?", group) // 使用反引号包围group + query = query.Where("id = ? AND "+groupCol+" = ?", keywordInt, group) + } else { + query = query.Where("id = ?", keywordInt) } - err = query.Find(&users).Error - if err != nil || len(users) > 0 { - return users, err - } - } - - err = nil - - query := DB.Unscoped().Omit("password") - likeCondition := "username LIKE ? OR email LIKE ? OR display_name LIKE ?" - if group != "" { - query = query.Where("("+likeCondition+") AND "+groupCol+" = ?", "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%", group) } else { - query = query.Where(likeCondition, "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%") + // 如果不是ID搜索,则使用模糊匹配 + likeCondition := "username LIKE ? OR email LIKE ? OR display_name LIKE ?" + if group != "" { + query = query.Where("("+likeCondition+") AND "+groupCol+" = ?", + "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%", group) + } else { + query = query.Where(likeCondition, + "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%") + } } - err = query.Find(&users).Error - return users, err + // 获取总数 + err = query.Count(&total).Error + if err != nil { + tx.Rollback() + return nil, 0, err + } + + // 获取分页数据 + err = query.Omit("password").Order("id desc").Limit(num).Offset(startIdx).Find(&users).Error + if err != nil { + tx.Rollback() + return nil, 0, err + } + + // 提交事务 + if err = tx.Commit().Error; err != nil { + return nil, 0, err + } + + return users, total, nil } func GetUserById(id int, selectAll bool) (*User, error) { diff --git a/web/src/components/UsersTable.js b/web/src/components/UsersTable.js index 24d6d873..bf308911 100644 --- a/web/src/components/UsersTable.js +++ b/web/src/components/UsersTable.js @@ -327,20 +327,22 @@ const UsersTable = () => { } }; - const searchUsers = async (searchKeyword, searchGroup) => { + const searchUsers = async (startIdx, pageSize, searchKeyword, searchGroup) => { if (searchKeyword === '' && searchGroup === '') { - // if keyword is blank, load files instead. - await loadUsers(activePage, pageSize); - return; + // if keyword is blank, load files instead. + await loadUsers(startIdx, pageSize); + return; } setSearching(true); - const res = await API.get(`/api/user/search?keyword=${searchKeyword}&group=${searchGroup}`); + const res = await API.get(`/api/user/search?keyword=${searchKeyword}&group=${searchGroup}&p=${startIdx}&page_size=${pageSize}`); const { success, message, data } = res.data; if (success) { - setUsers(data); - setActivePage(1); + const newPageData = data.items; + setActivePage(data.page); + setUserCount(data.total); + setUserFormat(newPageData); } else { - showError(message); + showError(message); } setSearching(false); }; @@ -349,30 +351,15 @@ const UsersTable = () => { setSearchKeyword(value.trim()); }; - const sortUser = (key) => { - if (users.length === 0) return; - setLoading(true); - let sortedUsers = [...users]; - sortedUsers.sort((a, b) => { - return ('' + a[key]).localeCompare(b[key]); - }); - if (sortedUsers[0].id === users[0].id) { - sortedUsers.reverse(); - } - setUsers(sortedUsers); - setLoading(false); - }; - const handlePageChange = (page) => { setActivePage(page); - loadUsers(page, pageSize).then((r) => {}); + if (searchKeyword === '' && searchGroup === '') { + loadUsers(page, pageSize).then(); + } else { + searchUsers(page, pageSize, searchKeyword, searchGroup).then(); + } }; - const pageData = users.slice( - (activePage - 1) * ITEMS_PER_PAGE, - activePage * ITEMS_PER_PAGE, - ); - const closeAddUser = () => { setShowAddUser(false); }; @@ -438,29 +425,32 @@ const UsersTable = () => { >