diff --git a/docs/swagger/docs.go b/docs/swagger/docs.go index a5d3c025..3ff3093b 100644 --- a/docs/swagger/docs.go +++ b/docs/swagger/docs.go @@ -3344,6 +3344,12 @@ const docTemplate = `{ "description": "The offset for pagination", "name": "offset", "in": "query" + }, + { + "type": "string", + "description": "Search keywords", + "name": "search", + "in": "query" } ], "responses": { diff --git a/docs/swagger/swagger.json b/docs/swagger/swagger.json index eb442a5f..ab6a5913 100644 --- a/docs/swagger/swagger.json +++ b/docs/swagger/swagger.json @@ -3337,6 +3337,12 @@ "description": "The offset for pagination", "name": "offset", "in": "query" + }, + { + "type": "string", + "description": "Search keywords", + "name": "search", + "in": "query" } ], "responses": { diff --git a/docs/swagger/swagger.yaml b/docs/swagger/swagger.yaml index 59d527cd..e5fd1f7c 100644 --- a/docs/swagger/swagger.yaml +++ b/docs/swagger/swagger.yaml @@ -3172,6 +3172,10 @@ paths: in: query name: offset type: integer + - description: Search keywords + in: query + name: search + type: string produces: - application/json responses: diff --git a/server/handler/user_list.go b/server/handler/user_list.go index d7a67333..ec68baeb 100644 --- a/server/handler/user_list.go +++ b/server/handler/user_list.go @@ -5,11 +5,13 @@ import ( "github.com/ArtalkJS/Artalk/internal/entity" "github.com/ArtalkJS/Artalk/server/common" "github.com/gofiber/fiber/v2" + "gorm.io/gorm" ) type ParamsUserList struct { - Limit int `query:"limit" json:"limit" validate:"optional"` // The limit for pagination - Offset int `query:"offset" json:"offset" validate:"optional"` // The offset for pagination + Limit int `query:"limit" json:"limit" validate:"optional"` // The limit for pagination + Offset int `query:"offset" json:"offset" validate:"optional"` // The offset for pagination + Search string `query:"search" json:"search" validate:"optional"` // Search keywords } type ResponseAdminUserList struct { @@ -38,24 +40,30 @@ func UserList(app *core.App, router fiber.Router) { return resp } - // 准备 query + // Prepare query q := app.Dao().DB().Model(&entity.User{}).Order("created_at DESC") - // 总共条数 + // Total count var total int64 q.Count(&total) - // 类型筛选 + // User type if listType == "admin" { q = q.Where("is_admin = ?", true) } else if listType == "in_conf" { q = q.Where("is_in_conf = ?", true) } - // 数据分页 + // Search + q = q.Scopes(func(d *gorm.DB) *gorm.DB { + return d.Where("LOWER(name) LIKE LOWER(?) OR LOWER(email) LIKE LOWER(?) OR badge_name = ? OR last_ip = ?", + "%"+p.Search+"%", "%"+p.Search+"%", p.Search, p.Search) + }) + + // Pagination q = q.Scopes(Paginate(p.Offset, p.Limit)) - // 查找 + // Find users var users []entity.User q.Find(&users) diff --git a/ui/artalk-sidebar/src/pages/comments.vue b/ui/artalk-sidebar/src/pages/comments.vue index aaa1418f..60d764b9 100644 --- a/ui/artalk-sidebar/src/pages/comments.vue +++ b/ui/artalk-sidebar/src/pages/comments.vue @@ -10,7 +10,6 @@ const user = useUserStore() const nav = useNavStore() const { curtTab } = storeToRefs(nav) const { site: curtSite } = storeToRefs(user) -const { t } = useI18n() const search = ref('') @@ -81,7 +80,7 @@ onMounted(() => { listEl.value?.append($el) - // 搜索功能 + // Comments search nav.enableSearch( (value: string) => { search.value = value diff --git a/ui/artalk-sidebar/src/pages/users.vue b/ui/artalk-sidebar/src/pages/users.vue index 8d4ce32e..90bb99da 100644 --- a/ui/artalk-sidebar/src/pages/users.vue +++ b/ui/artalk-sidebar/src/pages/users.vue @@ -6,7 +6,6 @@ import { artalk, bootParams } from '../global' import Pagination from '../components/Pagination.vue' const nav = useNavStore() -const router = useRouter() const { curtTab } = storeToRefs(nav) const users = ref([]) const { t } = useI18n() @@ -14,11 +13,13 @@ const { t } = useI18n() const pageSize = ref(30) const pageTotal = ref(0) const pagination = ref>() -const curtType = ref('all') +const curtType = ref<'all' | 'admin' | 'in_conf' | undefined>('all') const addingUser = ref(false) const editingUser = ref() +const search = ref('') + onMounted(() => { nav.updateTabs( { @@ -43,22 +44,36 @@ onMounted(() => { addingUser.value = false editingUser.value = undefined - curtType.value = tab + curtType.value = tab as any pagination.value?.reset() reqUsers(0) } }) reqUsers(0) + + // Users search + nav.enableSearch( + (value: string) => { + search.value = value + reqUsers(0) + }, + () => { + if (search.value === '') return + search.value = '' + reqUsers(0) + }, + ) }) function reqUsers(offset: number) { nav.setPageLoading(true) artalk?.ctx .getApi() - .users.getUsers(curtType.value as any, { + .users.getUsers(curtType.value, { offset, limit: pageSize.value, + search: search.value, }) .then((res) => { pageTotal.value = res.data.count diff --git a/ui/artalk/src/api/v2.ts b/ui/artalk/src/api/v2.ts index 3956e3bd..31e7d352 100644 --- a/ui/artalk/src/api/v2.ts +++ b/ui/artalk/src/api/v2.ts @@ -2418,6 +2418,8 @@ export class Api extends HttpClient