diff --git a/docs/docs.go b/docs/docs.go index 81ccb1a7..b41a96b3 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -56,6 +56,12 @@ const docTemplate = `{ "description": "user status", "name": "status", "in": "query" + }, + { + "type": "string", + "description": "answer id or question title", + "name": "query", + "in": "query" } ], "responses": { @@ -173,6 +179,12 @@ const docTemplate = `{ "description": "user status", "name": "status", "in": "query" + }, + { + "type": "string", + "description": "question id or title", + "name": "query", + "in": "query" } ], "responses": { @@ -709,19 +721,12 @@ const docTemplate = `{ }, { "type": "string", - "description": "username", - "name": "username", - "in": "query" - }, - { - "type": "string", - "description": "email", - "name": "e_mail", + "description": "search query: email, username or id:[id]", + "name": "query", "in": "query" }, { "enum": [ - "normal", "suspended", "deleted", "inactive" diff --git a/docs/swagger.json b/docs/swagger.json index c92a6b1e..05097e5f 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -44,6 +44,12 @@ "description": "user status", "name": "status", "in": "query" + }, + { + "type": "string", + "description": "answer id or question title", + "name": "query", + "in": "query" } ], "responses": { @@ -161,6 +167,12 @@ "description": "user status", "name": "status", "in": "query" + }, + { + "type": "string", + "description": "question id or title", + "name": "query", + "in": "query" } ], "responses": { @@ -697,19 +709,12 @@ }, { "type": "string", - "description": "username", - "name": "username", - "in": "query" - }, - { - "type": "string", - "description": "email", - "name": "e_mail", + "description": "search query: email, username or id:[id]", + "name": "query", "in": "query" }, { "enum": [ - "normal", "suspended", "deleted", "inactive" diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 5a261821..9e36de5b 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -1390,6 +1390,10 @@ paths: in: query name: status type: string + - description: answer id or question title + in: query + name: query + type: string produces: - application/json responses: @@ -1463,6 +1467,10 @@ paths: in: query name: status type: string + - description: question id or title + in: query + name: query + type: string produces: - application/json responses: @@ -1788,17 +1796,12 @@ paths: in: query name: page_size type: integer - - description: username + - description: 'search query: email, username or id:[id]' in: query - name: username - type: string - - description: email - in: query - name: e_mail + name: query type: string - description: user status enum: - - normal - suspended - deleted - inactive diff --git a/internal/controller/question_controller.go b/internal/controller/question_controller.go index 620f1e41..dab6735f 100644 --- a/internal/controller/question_controller.go +++ b/internal/controller/question_controller.go @@ -365,6 +365,7 @@ func (qc *QuestionController) UserCollectionList(ctx *gin.Context) { // @Param page query int false "page size" // @Param page_size query int false "page size" // @Param status query string false "user status" Enums(available, closed, deleted) +// @Param query query string false "question id or title" // @Success 200 {object} handler.RespBody // @Router /answer/admin/api/question/page [get] func (qc *QuestionController) CmsSearchList(ctx *gin.Context) { @@ -390,6 +391,7 @@ func (qc *QuestionController) CmsSearchList(ctx *gin.Context) { // @Param page query int false "page size" // @Param page_size query int false "page size" // @Param status query string false "user status" Enums(available,deleted) +// @Param query query string false "answer id or question title" // @Success 200 {object} handler.RespBody // @Router /answer/admin/api/answer/page [get] func (qc *QuestionController) CmsSearchAnswerList(ctx *gin.Context) { diff --git a/internal/controller_backyard/user_backyard_controller.go b/internal/controller_backyard/user_backyard_controller.go index 0c3177fb..03d56d96 100644 --- a/internal/controller_backyard/user_backyard_controller.go +++ b/internal/controller_backyard/user_backyard_controller.go @@ -45,9 +45,8 @@ func (uc *UserBackyardController) UpdateUserStatus(ctx *gin.Context) { // @Produce json // @Param page query int false "page size" // @Param page_size query int false "page size" -// @Param username query string false "username" -// @Param e_mail query string false "email" -// @Param status query string false "user status" Enums(normal, suspended, deleted, inactive) +// @Param query query string false "search query: email, username or id:[id]" +// @Param status query string false "user status" Enums(suspended, deleted, inactive) // @Success 200 {object} handler.RespBody{data=pager.PageModel{records=[]schema.GetUserPageResp}} // @Router /answer/admin/api/users/page [get] func (uc *UserBackyardController) GetUserPage(ctx *gin.Context) { diff --git a/internal/entity/answer_entity.go b/internal/entity/answer_entity.go index 3666f106..8c33d08c 100644 --- a/internal/entity/answer_entity.go +++ b/internal/entity/answer_entity.go @@ -43,7 +43,8 @@ type CmsAnswerSearch struct { Page int `json:"page" form:"page"` //Query number of pages PageSize int `json:"page_size" form:"page_size"` //Search page size Status int `json:"-" form:"-"` - StatusStr string `json:"status" form:"status"` //Status 1 Available 2 closed 10 Deleted + StatusStr string `json:"status" form:"status"` //Status 1 Available 2 closed 10 Deleted + Query string `validate:"omitempty,gt=0,lte=100" json:"query" form:"query" ` //Query string } type AdminSetAnswerStatusRequest struct { diff --git a/internal/repo/answer_repo.go b/internal/repo/answer_repo.go index dd4753e8..a4c42722 100644 --- a/internal/repo/answer_repo.go +++ b/internal/repo/answer_repo.go @@ -2,7 +2,10 @@ package repo import ( "context" + "strings" "time" + "unicode" + "xorm.io/builder" "github.com/answerdev/answer/internal/base/constant" "github.com/answerdev/answer/internal/base/data" @@ -202,11 +205,16 @@ func (ar *answerRepo) SearchList(ctx context.Context, search *entity.AnswerSearc } func (ar *answerRepo) CmsSearchList(ctx context.Context, search *entity.CmsAnswerSearch) ([]*entity.Answer, int64, error) { - var count int64 - var err error - if search.Status == 0 { - search.Status = 1 - } + var ( + count int64 + err error + session = ar.data.DB.Table([]string{entity.Answer{}.TableName(), "a"}).Select("a.*") + ) + + session.Where(builder.Eq{ + "a.status": search.Status, + }) + rows := make([]*entity.Answer, 0) if search.Page > 0 { search.Page = search.Page - 1 @@ -216,11 +224,42 @@ func (ar *answerRepo) CmsSearchList(ctx context.Context, search *entity.CmsAnswe if search.PageSize == 0 { search.PageSize = constant.Default_PageSize } + + // search by question title like or answer id + if len(search.Query) > 0 { + // check id search + var ( + idSearch = false + id = "" + ) + + if strings.Contains(search.Query, "id:") { + idSearch = true + id = strings.TrimSpace(strings.TrimPrefix(search.Query, "id:")) + for _, r := range id { + if !unicode.IsDigit(r) { + idSearch = false + break + } + } + } + + if idSearch { + session.And(builder.Eq{ + "id": id, + }) + } else { + session.Join("LEFT", []string{entity.Question{}.TableName(), "q"}, "q.id = a.question_id") + session.And(builder.Like{ + "q.title", search.Query, + }) + } + } + offset := search.Page * search.PageSize - session := ar.data.DB.Where("") - session = session.And("status =?", search.Status) - session = session.OrderBy("updated_at desc") - session = session.Limit(search.PageSize, offset) + session. + OrderBy("a.updated_at desc"). + Limit(search.PageSize, offset) count, err = session.FindAndCount(&rows) if err != nil { return rows, count, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() diff --git a/internal/repo/question_repo.go b/internal/repo/question_repo.go index f6f4e40b..3142bcd2 100644 --- a/internal/repo/question_repo.go +++ b/internal/repo/question_repo.go @@ -2,7 +2,10 @@ package repo import ( "context" + "strings" "time" + "unicode" + "xorm.io/builder" "github.com/answerdev/answer/internal/base/constant" "github.com/answerdev/answer/internal/base/data" @@ -225,8 +228,16 @@ func (qr *questionRepo) SearchList(ctx context.Context, search *schema.QuestionS } func (qr *questionRepo) CmsSearchList(ctx context.Context, search *schema.CmsQuestionSearch) ([]*entity.Question, int64, error) { - var count int64 - var err error + var ( + count int64 + err error + session = qr.data.DB.Table("question") + ) + + session.Where(builder.Eq{ + "status": search.Status, + }) + rows := make([]*entity.Question, 0) if search.Page > 0 { search.Page = search.Page - 1 @@ -236,11 +247,40 @@ func (qr *questionRepo) CmsSearchList(ctx context.Context, search *schema.CmsQue if search.PageSize == 0 { search.PageSize = constant.Default_PageSize } + + // search by question title like or question id + if len(search.Query) > 0 { + // check id search + var ( + idSearch = false + id = "" + ) + if strings.Contains(search.Query, "id:") { + idSearch = true + id = strings.TrimSpace(strings.TrimPrefix(search.Query, "id:")) + for _, r := range id { + if !unicode.IsDigit(r) { + idSearch = false + break + } + } + } + + if idSearch { + session.And(builder.Eq{ + "id": id, + }) + } else { + session.And(builder.Like{ + "title", search.Query, + }) + } + } + offset := search.Page * search.PageSize - session := qr.data.DB.Table("question") - session = session.And("status =?", search.Status) - session = session.OrderBy("updated_at desc") - session = session.Limit(search.PageSize, offset) + + session.OrderBy("updated_at desc"). + Limit(search.PageSize, offset) count, err = session.FindAndCount(&rows) if err != nil { err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() diff --git a/internal/repo/user/user_backyard_repo.go b/internal/repo/user/user_backyard_repo.go index 06ce7d2f..790d7c41 100644 --- a/internal/repo/user/user_backyard_repo.go +++ b/internal/repo/user/user_backyard_repo.go @@ -3,7 +3,11 @@ package user import ( "context" "encoding/json" + "net/mail" + "strings" "time" + "unicode" + "xorm.io/builder" "github.com/answerdev/answer/internal/base/constant" "github.com/answerdev/answer/internal/base/data" @@ -68,7 +72,7 @@ func (ur *userBackyardRepo) GetUserInfo(ctx context.Context, userID string) (use } // GetUserPage get user page -func (ur *userBackyardRepo) GetUserPage(ctx context.Context, page, pageSize int, user *entity.User) (users []*entity.User, total int64, err error) { +func (ur *userBackyardRepo) GetUserPage(ctx context.Context, page, pageSize int, user *entity.User, query string) (users []*entity.User, total int64, err error) { users = make([]*entity.User, 0) session := ur.data.DB.NewSession() if user.Status == entity.UserStatusDeleted { @@ -78,6 +82,40 @@ func (ur *userBackyardRepo) GetUserPage(ctx context.Context, page, pageSize int, } else { session.Desc("created_at") } + + if len(query) > 0 { + if email, e := mail.ParseAddress(query); e == nil { + session.And(builder.Eq{"e_mail": email.Address}) + } else { + var ( + idSearch = false + id = "" + ) + + if strings.Contains(query, "id:") { + idSearch = true + id = strings.TrimSpace(strings.TrimPrefix(query, "id:")) + for _, r := range id { + if !unicode.IsDigit(r) { + idSearch = false + break + } + } + } + + if idSearch { + session.And(builder.Eq{ + "id": id, + }) + } else { + session.And(builder.Or( + builder.Like{"username", query}, + builder.Like{"display_name", query}, + )) + } + } + } + total, err = pager.Help(page, pageSize, &users, user, session) if err != nil { err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() diff --git a/internal/schema/backyard_user_schema.go b/internal/schema/backyard_user_schema.go index bccf1b63..de158146f 100644 --- a/internal/schema/backyard_user_schema.go +++ b/internal/schema/backyard_user_schema.go @@ -26,10 +26,8 @@ type GetUserPageReq struct { Page int `validate:"omitempty,min=1" form:"page"` // page size PageSize int `validate:"omitempty,min=1" form:"page_size"` - // username - Username string `validate:"omitempty,gt=0,lte=50" form:"username"` // email - EMail string `validate:"omitempty,gt=0,lte=100" form:"e_mail"` + Query string `validate:"omitempty,gt=0,lte=100" form:"query"` // user status Status string `validate:"omitempty,oneof=suspended deleted inactive" form:"status"` } diff --git a/internal/schema/question_schema.go b/internal/schema/question_schema.go index 5bd3b4c1..7ca467b4 100644 --- a/internal/schema/question_schema.go +++ b/internal/schema/question_schema.go @@ -170,7 +170,8 @@ type CmsQuestionSearch struct { Page int `json:"page" form:"page"` //Query number of pages PageSize int `json:"page_size" form:"page_size"` //Search page size Status int `json:"-" form:"-"` - StatusStr string `json:"status" form:"status"` //Status 1 Available 2 closed 10 UserDeleted + StatusStr string `json:"status" form:"status"` //Status 1 Available 2 closed 10 UserDeleted + Query string `validate:"omitempty,gt=0,lte=100" json:"query" form:"query" ` //Query string } type AdminSetQuestionStatusRequest struct { diff --git a/internal/service/answer_common/answer.go b/internal/service/answer_common/answer.go index 7fc65a6f..a974d313 100644 --- a/internal/service/answer_common/answer.go +++ b/internal/service/answer_common/answer.go @@ -42,6 +42,9 @@ func (as *AnswerCommon) SearchAnswered(ctx context.Context, userId, questionId s } func (as *AnswerCommon) CmsSearchList(ctx context.Context, search *entity.CmsAnswerSearch) ([]*entity.Answer, int64, error) { + if search.Status == 0 { + search.Status = 1 + } return as.answerRepo.CmsSearchList(ctx, search) } diff --git a/internal/service/user_backyard/user_backyard.go b/internal/service/user_backyard/user_backyard.go index 4dfe8433..b0aa8ad9 100644 --- a/internal/service/user_backyard/user_backyard.go +++ b/internal/service/user_backyard/user_backyard.go @@ -17,7 +17,7 @@ import ( type UserBackyardRepo interface { UpdateUserStatus(ctx context.Context, userID string, userStatus, mailStatus int, email string) (err error) GetUserInfo(ctx context.Context, userID string) (user *entity.User, exist bool, err error) - GetUserPage(ctx context.Context, page, pageSize int, user *entity.User) (users []*entity.User, total int64, err error) + GetUserPage(ctx context.Context, page, pageSize int, user *entity.User, query string) (users []*entity.User, total int64, err error) } // UserBackyardService user service @@ -91,7 +91,7 @@ func (us *UserBackyardService) GetUserPage(ctx context.Context, req *schema.GetU user.Status = entity.UserStatusDeleted } - users, total, err := us.userRepo.GetUserPage(ctx, req.Page, req.PageSize, user) + users, total, err := us.userRepo.GetUserPage(ctx, req.Page, req.PageSize, user, req.Query) if err != nil { return }