refactor(answer): refactor admin question answer page list

This commit is contained in:
LinkinStars 2023-06-20 16:55:43 +08:00
parent 3ed9568614
commit 92c5bb6616
12 changed files with 162 additions and 191 deletions

View File

@ -49,7 +49,7 @@ const docTemplate = `{
"tags": [
"admin"
],
"summary": "AdminSearchAnswerList",
"summary": "AdminAnswerPage admin answer page",
"parameters": [
{
"type": "integer",
@ -379,7 +379,7 @@ const docTemplate = `{
"tags": [
"admin"
],
"summary": "AdminSearchList",
"summary": "AdminQuestionPage admin question page",
"parameters": [
{
"type": "integer",
@ -8186,7 +8186,7 @@ const docTemplate = `{
"type": "string"
},
"site_seo": {
"$ref": "#/definitions/schema.SiteSeoReq"
"$ref": "#/definitions/schema.SiteSeoResp"
},
"site_users": {
"$ref": "#/definitions/schema.SiteUsersResp"

View File

@ -37,7 +37,7 @@
"tags": [
"admin"
],
"summary": "AdminSearchAnswerList",
"summary": "AdminAnswerPage admin answer page",
"parameters": [
{
"type": "integer",
@ -367,7 +367,7 @@
"tags": [
"admin"
],
"summary": "AdminSearchList",
"summary": "AdminQuestionPage admin question page",
"parameters": [
{
"type": "integer",
@ -8174,7 +8174,7 @@
"type": "string"
},
"site_seo": {
"$ref": "#/definitions/schema.SiteSeoReq"
"$ref": "#/definitions/schema.SiteSeoResp"
},
"site_users": {
"$ref": "#/definitions/schema.SiteUsersResp"

View File

@ -1507,7 +1507,7 @@ definitions:
revision:
type: string
site_seo:
$ref: '#/definitions/schema.SiteSeoReq'
$ref: '#/definitions/schema.SiteSeoResp'
site_users:
$ref: '#/definitions/schema.SiteUsersResp'
theme:
@ -2335,7 +2335,7 @@ paths:
$ref: '#/definitions/handler.RespBody'
security:
- ApiKeyAuth: []
summary: AdminSearchAnswerList
summary: AdminAnswerPage admin answer page
tags:
- admin
/answer/admin/api/answer/status:
@ -2533,7 +2533,7 @@ paths:
$ref: '#/definitions/handler.RespBody'
security:
- ApiKeyAuth: []
summary: AdminSearchList
summary: AdminQuestionPage admin question page
tags:
- admin
/answer/admin/api/question/status:

View File

@ -7,7 +7,6 @@ import (
"github.com/answerdev/answer/internal/base/reason"
"github.com/answerdev/answer/internal/base/translator"
"github.com/answerdev/answer/internal/base/validator"
"github.com/answerdev/answer/internal/entity"
"github.com/answerdev/answer/internal/schema"
"github.com/answerdev/answer/internal/service"
"github.com/answerdev/answer/internal/service/permission"
@ -709,8 +708,8 @@ func (qc *QuestionController) PersonalCollectionPage(ctx *gin.Context) {
handler.HandleResponse(ctx, err, resp)
}
// AdminSearchList godoc
// @Summary AdminSearchList
// AdminQuestionPage admin question page
// @Summary AdminQuestionPage admin question page
// @Description Status:[available,closed,deleted]
// @Tags admin
// @Accept json
@ -722,21 +721,19 @@ func (qc *QuestionController) PersonalCollectionPage(ctx *gin.Context) {
// @Param query query string false "question id or title"
// @Success 200 {object} handler.RespBody
// @Router /answer/admin/api/question/page [get]
func (qc *QuestionController) AdminSearchList(ctx *gin.Context) {
req := &schema.AdminQuestionSearch{}
func (qc *QuestionController) AdminQuestionPage(ctx *gin.Context) {
req := &schema.AdminQuestionPageReq{}
if handler.BindAndCheck(ctx, req) {
return
}
userID := middleware.GetLoginUserIDFromContext(ctx)
questionList, count, err := qc.questionService.AdminSearchList(ctx, req, userID)
handler.HandleResponse(ctx, err, gin.H{
"list": questionList,
"count": count,
})
req.LoginUserID = middleware.GetLoginUserIDFromContext(ctx)
resp, err := qc.questionService.AdminQuestionPage(ctx, req)
handler.HandleResponse(ctx, err, resp)
}
// AdminSearchAnswerList godoc
// @Summary AdminSearchAnswerList
// AdminAnswerPage admin answer page
// @Summary AdminAnswerPage admin answer page
// @Description Status:[available,deleted]
// @Tags admin
// @Accept json
@ -749,21 +746,15 @@ func (qc *QuestionController) AdminSearchList(ctx *gin.Context) {
// @Param question_id query string false "question id"
// @Success 200 {object} handler.RespBody
// @Router /answer/admin/api/answer/page [get]
func (qc *QuestionController) AdminSearchAnswerList(ctx *gin.Context) {
req := &entity.AdminAnswerSearch{}
func (qc *QuestionController) AdminAnswerPage(ctx *gin.Context) {
req := &schema.AdminAnswerPageReq{}
if handler.BindAndCheck(ctx, req) {
return
}
req.QuestionID = uid.DeShortID(req.QuestionID)
if req.QuestionID == "0" {
req.QuestionID = ""
}
userID := middleware.GetLoginUserIDFromContext(ctx)
questionList, count, err := qc.questionService.AdminSearchAnswerList(ctx, req, userID)
handler.HandleResponse(ctx, err, gin.H{
"list": questionList,
"count": count,
})
req.LoginUserID = middleware.GetLoginUserIDFromContext(ctx)
resp, err := qc.questionService.AdminAnswerPage(ctx, req)
handler.HandleResponse(ctx, err, resp)
}
// AdminSetQuestionStatus godoc

View File

@ -42,15 +42,6 @@ type AnswerSearch struct {
PageSize int `json:"page_size" form:"page_size"` // Search page size
}
type AdminAnswerSearch 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
Query string `validate:"omitempty,gt=0,lte=100" json:"query" form:"query" ` //Query string
QuestionID string `validate:"omitempty,gt=0,lte=24" json:"question_id" form:"question_id" ` //Query string
}
// TableName answer table name
func (Answer) TableName() string {
return "answer"

View File

@ -2,15 +2,11 @@ package answer
import (
"context"
"strings"
"time"
"unicode"
"github.com/answerdev/answer/internal/base/handler"
"xorm.io/builder"
"github.com/answerdev/answer/internal/base/constant"
"github.com/answerdev/answer/internal/base/data"
"github.com/answerdev/answer/internal/base/handler"
"github.com/answerdev/answer/internal/base/pager"
"github.com/answerdev/answer/internal/base/reason"
"github.com/answerdev/answer/internal/entity"
@ -295,82 +291,31 @@ func (ar *answerRepo) SearchList(ctx context.Context, search *entity.AnswerSearc
return rows, count, nil
}
func (ar *answerRepo) AdminSearchList(ctx context.Context, search *entity.AdminAnswerSearch) ([]*entity.Answer, int64, error) {
var (
count int64
err error
session = ar.data.DB.Context(ctx).Table([]string{entity.Answer{}.TableName(), "a"}).Select("a.*")
)
if search.QuestionID != "" {
search.QuestionID = uid.DeShortID(search.QuestionID)
}
session.Where(builder.Eq{
"a.status": search.Status,
})
rows := make([]*entity.Answer, 0)
if search.Page > 0 {
search.Page = search.Page - 1
} else {
search.Page = 0
}
if search.PageSize == 0 {
search.PageSize = constant.DefaultPageSize
}
// 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, "answer:") {
idSearch = true
id = strings.TrimSpace(strings.TrimPrefix(search.Query, "answer:"))
id = uid.DeShortID(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,
})
func (ar *answerRepo) AdminSearchList(ctx context.Context, req *schema.AdminAnswerPageReq) (
resp []*entity.Answer, total int64, err error) {
cond := &entity.Answer{}
session := ar.data.DB.Context(ctx)
if len(req.QuestionID) == 0 && len(req.AnswerID) == 0 {
session.Join("INNER", "question", "answer.question_id = question.id")
if len(req.QuestionTitle) > 0 {
session.Where("question.title like ?", "%"+req.QuestionTitle+"%")
}
}
// check search by question id
if len(search.QuestionID) > 0 {
session.And(builder.Eq{
"question_id": search.QuestionID,
})
if len(req.AnswerID) > 0 {
cond.ID = req.AnswerID
}
if len(req.QuestionID) > 0 {
session.Where("answer.question_id = ?", req.QuestionID)
}
if req.Status > 0 {
cond.Status = req.Status
}
session.Desc("answer.created_at")
offset := search.Page * search.PageSize
session.
OrderBy("a.created_at desc").
Limit(search.PageSize, offset)
count, err = session.FindAndCount(&rows)
resp = make([]*entity.Answer, 0)
total, err = pager.Help(req.Page, req.PageSize, &resp, cond, session)
if err != nil {
return rows, count, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
return nil, 0, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
if handler.GetEnableShortID(ctx) {
for _, item := range rows {
item.ID = uid.EnShortID(item.ID)
item.QuestionID = uid.EnShortID(item.QuestionID)
}
}
return rows, count, nil
return resp, total, nil
}

View File

@ -333,7 +333,7 @@ func (qr *questionRepo) GetQuestionPage(ctx context.Context, page, pageSize int,
return questionList, total, err
}
func (qr *questionRepo) AdminSearchList(ctx context.Context, search *schema.AdminQuestionSearch) ([]*entity.Question, int64, error) {
func (qr *questionRepo) AdminQuestionPage(ctx context.Context, search *schema.AdminQuestionPageReq) ([]*entity.Question, int64, error) {
var (
count int64
err error

View File

@ -244,9 +244,9 @@ func (a *AnswerAPIRouter) RegisterAnswerAPIRouter(r *gin.RouterGroup) {
}
func (a *AnswerAPIRouter) RegisterAnswerAdminAPIRouter(r *gin.RouterGroup) {
r.GET("/question/page", a.questionController.AdminSearchList)
r.GET("/question/page", a.questionController.AdminQuestionPage)
r.PUT("/question/status", a.questionController.AdminSetQuestionStatus)
r.GET("/answer/page", a.questionController.AdminSearchAnswerList)
r.GET("/answer/page", a.questionController.AdminAnswerPage)
r.PUT("/answer/status", a.answerController.AdminSetAnswerStatus)
// report

View File

@ -1,10 +1,13 @@
package schema
import (
"strings"
"time"
"github.com/answerdev/answer/internal/base/validator"
"github.com/answerdev/answer/internal/entity"
"github.com/answerdev/answer/pkg/converter"
"github.com/answerdev/answer/pkg/uid"
)
const (
@ -361,12 +364,62 @@ type QuestionPageRespOperator struct {
DisplayName string `json:"display_name"`
}
type AdminQuestionSearch 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
Query string `validate:"omitempty,gt=0,lte=100" json:"query" form:"query" ` //Query string
type AdminQuestionPageReq struct {
Page int `validate:"omitempty,min=1" form:"page"`
PageSize int `validate:"omitempty,min=1" form:"page_size"`
StatusCond string `validate:"omitempty,oneof=normal closed deleted" form:"status"`
Query string `validate:"omitempty,gt=0,lte=100" json:"query" form:"query" `
Status int `json:"-"`
LoginUserID string `json:"-"`
}
func (req *AdminQuestionPageReq) Check() (errField []*validator.FormErrorField, err error) {
status, ok := entity.AdminQuestionSearchStatus[req.StatusCond]
if ok {
req.Status = status
}
if req.Status == 0 {
req.Status = 1
}
return nil, nil
}
// AdminAnswerPageReq admin answer page req
type AdminAnswerPageReq struct {
Page int `validate:"omitempty,min=1" form:"page"`
PageSize int `validate:"omitempty,min=1" form:"page_size"`
StatusCond string `validate:"omitempty,oneof=normal deleted" form:"status"`
Query string `validate:"omitempty,gt=0,lte=100" form:"query"`
QuestionID string `validate:"omitempty,gt=0,lte=24" form:"question_id"`
QuestionTitle string `json:"-"`
AnswerID string `json:"-"`
Status int `json:"-"`
LoginUserID string `json:"-"`
}
func (req *AdminAnswerPageReq) Check() (errField []*validator.FormErrorField, err error) {
req.QuestionID = uid.DeShortID(req.QuestionID)
if req.QuestionID == "0" {
req.QuestionID = ""
}
if status, ok := entity.AdminAnswerSearchStatus[req.StatusCond]; ok {
req.Status = status
}
if req.Status == 0 {
req.Status = 1
}
// parse query condition
if len(req.Query) > 0 {
prefix := "answer:"
if strings.Contains(req.Query, prefix) {
req.AnswerID = uid.DeShortID(strings.TrimSpace(strings.TrimPrefix(req.Query, prefix)))
} else {
req.QuestionTitle = strings.TrimSpace(req.Query)
}
}
return nil, nil
}
type AdminSetQuestionStatusRequest struct {

View File

@ -3,9 +3,11 @@ package answercommon
import (
"context"
"github.com/answerdev/answer/internal/base/handler"
"github.com/answerdev/answer/internal/entity"
"github.com/answerdev/answer/internal/schema"
"github.com/answerdev/answer/pkg/htmltext"
"github.com/answerdev/answer/pkg/uid"
)
type AnswerRepo interface {
@ -21,7 +23,7 @@ type AnswerRepo interface {
GetCountByUserID(ctx context.Context, userID string) (int64, error)
GetByUserIDQuestionID(ctx context.Context, userID string, questionID string) (*entity.Answer, bool, error)
SearchList(ctx context.Context, search *entity.AnswerSearch) ([]*entity.Answer, int64, error)
AdminSearchList(ctx context.Context, search *entity.AdminAnswerSearch) ([]*entity.Answer, int64, error)
AdminSearchList(ctx context.Context, search *schema.AdminAnswerPageReq) ([]*entity.Answer, int64, error)
UpdateAnswerStatus(ctx context.Context, answer *entity.Answer) (err error)
GetAnswerCount(ctx context.Context) (count int64, err error)
}
@ -45,11 +47,16 @@ func (as *AnswerCommon) SearchAnswered(ctx context.Context, userID, questionID s
return has, nil
}
func (as *AnswerCommon) AdminSearchList(ctx context.Context, search *entity.AdminAnswerSearch) ([]*entity.Answer, int64, error) {
if search.Status == 0 {
search.Status = 1
func (as *AnswerCommon) AdminSearchList(ctx context.Context, req *schema.AdminAnswerPageReq) (
resp []*entity.Answer, count int64, err error) {
resp, count, err = as.answerRepo.AdminSearchList(ctx, req)
if handler.GetEnableShortID(ctx) {
for _, item := range resp {
item.ID = uid.EnShortID(item.ID)
item.QuestionID = uid.EnShortID(item.QuestionID)
}
}
return as.answerRepo.AdminSearchList(ctx, search)
return resp, count, err
}
func (as *AnswerCommon) Search(ctx context.Context, search *entity.AnswerSearch) ([]*entity.Answer, int64, error) {

View File

@ -48,7 +48,7 @@ type QuestionRepo interface {
UpdateAccepted(ctx context.Context, question *entity.Question) (err error)
UpdateLastAnswer(ctx context.Context, question *entity.Question) (err error)
FindByID(ctx context.Context, id []string) (questionList []*entity.Question, err error)
AdminSearchList(ctx context.Context, search *schema.AdminQuestionSearch) ([]*entity.Question, int64, error)
AdminQuestionPage(ctx context.Context, search *schema.AdminQuestionPageReq) ([]*entity.Question, int64, error)
GetQuestionCount(ctx context.Context) (count int64, err error)
GetUserQuestionCount(ctx context.Context, userID string) (count int64, err error)
GetQuestionCountByIDs(ctx context.Context, ids []string) (count int64, err error)
@ -68,7 +68,7 @@ type QuestionCommon struct {
metaService *meta.MetaService
configService *config.ConfigService
activityQueueService activity_queue.ActivityQueueService
data *data.Data
data *data.Data
}
func NewQuestionCommon(questionRepo QuestionRepo,
@ -96,7 +96,7 @@ func NewQuestionCommon(questionRepo QuestionRepo,
metaService: metaService,
configService: configService,
activityQueueService: activityQueueService,
data: data,
data: data,
}
}

View File

@ -1256,89 +1256,73 @@ func (qs *QuestionService) AdminSetQuestionStatus(ctx context.Context, questionI
return nil
}
func (qs *QuestionService) AdminSearchList(ctx context.Context, search *schema.AdminQuestionSearch, loginUserID string) ([]*schema.AdminQuestionInfo, int64, error) {
func (qs *QuestionService) AdminQuestionPage(
ctx context.Context, req *schema.AdminQuestionPageReq) (
resp *pager.PageModel, err error) {
list := make([]*schema.AdminQuestionInfo, 0)
status, ok := entity.AdminQuestionSearchStatus[search.StatusStr]
if ok {
search.Status = status
}
if search.Status == 0 {
search.Status = 1
}
dblist, count, err := qs.questionRepo.AdminSearchList(ctx, search)
questionList, count, err := qs.questionRepo.AdminQuestionPage(ctx, req)
if err != nil {
return list, count, err
return nil, err
}
userIds := make([]string, 0)
for _, dbitem := range dblist {
for _, info := range questionList {
item := &schema.AdminQuestionInfo{}
_ = copier.Copy(item, dbitem)
item.CreateTime = dbitem.CreatedAt.Unix()
item.UpdateTime = dbitem.PostUpdateTime.Unix()
item.EditTime = dbitem.UpdatedAt.Unix()
_ = copier.Copy(item, info)
item.CreateTime = info.CreatedAt.Unix()
item.UpdateTime = info.PostUpdateTime.Unix()
item.EditTime = info.UpdatedAt.Unix()
list = append(list, item)
userIds = append(userIds, dbitem.UserID)
userIds = append(userIds, info.UserID)
}
userInfoMap, err := qs.userCommon.BatchUserBasicInfoByID(ctx, userIds)
if err != nil {
return list, count, err
return nil, err
}
for _, item := range list {
_, ok = userInfoMap[item.UserID]
if ok {
item.UserInfo = userInfoMap[item.UserID]
if u, ok := userInfoMap[item.UserID]; ok {
item.UserInfo = u
}
}
return list, count, nil
return pager.NewPageModel(count, list), nil
}
// AdminSearchList
func (qs *QuestionService) AdminSearchAnswerList(ctx context.Context, search *entity.AdminAnswerSearch, loginUserID string) ([]*schema.AdminAnswerInfo, int64, error) {
answerlist := make([]*schema.AdminAnswerInfo, 0)
status, ok := entity.AdminAnswerSearchStatus[search.StatusStr]
if ok {
search.Status = status
}
if search.Status == 0 {
search.Status = 1
}
dblist, count, err := qs.questioncommon.AnswerCommon.AdminSearchList(ctx, search)
// AdminAnswerPage search answer list
func (qs *QuestionService) AdminAnswerPage(ctx context.Context, req *schema.AdminAnswerPageReq) (
resp *pager.PageModel, err error) {
answerList, count, err := qs.questioncommon.AnswerCommon.AdminSearchList(ctx, req)
if err != nil {
return answerlist, count, err
return nil, err
}
questionIDs := make([]string, 0)
userIds := make([]string, 0)
for _, item := range dblist {
answerinfo := qs.questioncommon.AnswerCommon.AdminShowFormat(ctx, item)
answerlist = append(answerlist, answerinfo)
answerResp := make([]*schema.AdminAnswerInfo, 0)
for _, item := range answerList {
answerInfo := qs.questioncommon.AnswerCommon.AdminShowFormat(ctx, item)
answerResp = append(answerResp, answerInfo)
questionIDs = append(questionIDs, item.QuestionID)
userIds = append(userIds, item.UserID)
}
userInfoMap, err := qs.userCommon.BatchUserBasicInfoByID(ctx, userIds)
if err != nil {
return answerlist, count, err
return nil, err
}
questionMaps, err := qs.questioncommon.FindInfoByID(ctx, questionIDs, req.LoginUserID)
if err != nil {
return nil, err
}
questionMaps, err := qs.questioncommon.FindInfoByID(ctx, questionIDs, loginUserID)
if err != nil {
return answerlist, count, err
}
for _, item := range answerlist {
_, ok := questionMaps[item.QuestionID]
if ok {
item.QuestionInfo.Title = questionMaps[item.QuestionID].Title
for _, item := range answerResp {
if q, ok := questionMaps[item.QuestionID]; ok {
item.QuestionInfo.Title = q.Title
}
_, ok = userInfoMap[item.UserID]
if ok {
item.UserInfo = userInfoMap[item.UserID]
if u, ok := userInfoMap[item.UserID]; ok {
item.UserInfo = u
}
}
return answerlist, count, nil
return pager.NewPageModel(count, answerResp), nil
}
func (qs *QuestionService) changeQuestionToRevision(ctx context.Context, questionInfo *entity.Question, tags []*entity.Tag) (