mirror of https://gitee.com/answerdev/answer.git
Merge remote-tracking branch 'origin/feat/1.0.2/user' into test
This commit is contained in:
commit
7268fe2331
|
@ -204,7 +204,13 @@ backend:
|
||||||
other: "something else"
|
other: "something else"
|
||||||
desc:
|
desc:
|
||||||
other: "This post requires another reason not listed above."
|
other: "This post requires another reason not listed above."
|
||||||
|
operation_type:
|
||||||
|
asked:
|
||||||
|
other: "asked"
|
||||||
|
answered:
|
||||||
|
other: "answered"
|
||||||
|
modified:
|
||||||
|
other: "modified"
|
||||||
notification:
|
notification:
|
||||||
action:
|
action:
|
||||||
update_question:
|
update_question:
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/answerdev/answer/internal/base/handler"
|
"github.com/answerdev/answer/internal/base/handler"
|
||||||
"github.com/answerdev/answer/internal/base/middleware"
|
"github.com/answerdev/answer/internal/base/middleware"
|
||||||
|
"github.com/answerdev/answer/internal/base/pager"
|
||||||
"github.com/answerdev/answer/internal/base/reason"
|
"github.com/answerdev/answer/internal/base/reason"
|
||||||
"github.com/answerdev/answer/internal/base/validator"
|
"github.com/answerdev/answer/internal/base/validator"
|
||||||
"github.com/answerdev/answer/internal/entity"
|
"github.com/answerdev/answer/internal/entity"
|
||||||
|
@ -31,7 +30,7 @@ func NewQuestionController(questionService *service.QuestionService, rankService
|
||||||
// RemoveQuestion delete question
|
// RemoveQuestion delete question
|
||||||
// @Summary delete question
|
// @Summary delete question
|
||||||
// @Description delete question
|
// @Description delete question
|
||||||
// @Tags api-question
|
// @Tags Question
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
|
@ -62,7 +61,7 @@ func (qc *QuestionController) RemoveQuestion(ctx *gin.Context) {
|
||||||
// CloseQuestion Close question
|
// CloseQuestion Close question
|
||||||
// @Summary Close question
|
// @Summary Close question
|
||||||
// @Description Close question
|
// @Description Close question
|
||||||
// @Tags api-question
|
// @Tags Question
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
|
@ -92,7 +91,7 @@ func (qc *QuestionController) CloseQuestion(ctx *gin.Context) {
|
||||||
// ReopenQuestion reopen question
|
// ReopenQuestion reopen question
|
||||||
// @Summary reopen question
|
// @Summary reopen question
|
||||||
// @Description reopen question
|
// @Description reopen question
|
||||||
// @Tags api-question
|
// @Tags Question
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
|
@ -119,10 +118,10 @@ func (qc *QuestionController) ReopenQuestion(ctx *gin.Context) {
|
||||||
handler.HandleResponse(ctx, err, nil)
|
handler.HandleResponse(ctx, err, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetQuestion godoc
|
// GetQuestion get question details
|
||||||
// @Summary GetQuestion Question
|
// @Summary get question details
|
||||||
// @Description GetQuestion Question
|
// @Description get question details
|
||||||
// @Tags api-question
|
// @Tags Question
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
|
@ -161,7 +160,7 @@ func (qc *QuestionController) GetQuestion(ctx *gin.Context) {
|
||||||
// SimilarQuestion godoc
|
// SimilarQuestion godoc
|
||||||
// @Summary Search Similar Question
|
// @Summary Search Similar Question
|
||||||
// @Description Search Similar Question
|
// @Description Search Similar Question
|
||||||
// @Tags api-question
|
// @Tags Question
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param question_id query string true "question_id" default()
|
// @Param question_id query string true "question_id" default()
|
||||||
|
@ -181,65 +180,34 @@ func (qc *QuestionController) SimilarQuestion(ctx *gin.Context) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Index godoc
|
// QuestionPage get questions by page
|
||||||
// @Summary SearchQuestionList
|
// @Summary get questions by page
|
||||||
// @Description SearchQuestionList <br> "order" Enums(newest, active,frequent,score,unanswered)
|
// @Description get questions by page
|
||||||
// @Tags api-question
|
// @Tags Question
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param data body schema.QuestionSearch true "QuestionSearch"
|
// @Param data body schema.QuestionPageReq true "QuestionPageReq"
|
||||||
// @Success 200 {string} string ""
|
// @Success 200 {object} handler.RespBody{data=pager.PageModel{list=[]schema.QuestionPageResp}}
|
||||||
// @Router /answer/api/v1/question/page [get]
|
// @Router /answer/api/v1/question/page [get]
|
||||||
func (qc *QuestionController) Index(ctx *gin.Context) {
|
func (qc *QuestionController) QuestionPage(ctx *gin.Context) {
|
||||||
req := &schema.QuestionSearch{}
|
req := &schema.QuestionPageReq{}
|
||||||
if handler.BindAndCheck(ctx, req) {
|
if handler.BindAndCheck(ctx, req) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
userID := middleware.GetLoginUserIDFromContext(ctx)
|
req.LoginUserID = middleware.GetLoginUserIDFromContext(ctx)
|
||||||
list, count, err := qc.questionService.SearchList(ctx, req, userID)
|
|
||||||
|
questions, total, err := qc.questionService.GetQuestionPage(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handler.HandleResponse(ctx, err, nil)
|
handler.HandleResponse(ctx, err, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
handler.HandleResponse(ctx, nil, gin.H{
|
handler.HandleResponse(ctx, nil, pager.NewPageModel(total, questions))
|
||||||
"list": list,
|
|
||||||
"count": count,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// SearchList godoc
|
|
||||||
// @Summary SearchQuestionList
|
|
||||||
// @Description SearchQuestionList
|
|
||||||
// @Tags api-question
|
|
||||||
// @Accept json
|
|
||||||
// @Produce json
|
|
||||||
// @Param data body schema.QuestionSearch true "QuestionSearch"
|
|
||||||
// @Router /answer/api/v1/question/search [post]
|
|
||||||
// @Success 200 {string} string ""
|
|
||||||
func (qc *QuestionController) SearchList(c *gin.Context) {
|
|
||||||
Request := new(schema.QuestionSearch)
|
|
||||||
err := c.BindJSON(Request)
|
|
||||||
if err != nil {
|
|
||||||
handler.HandleResponse(c, err, nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx := context.Background()
|
|
||||||
userID := middleware.GetLoginUserIDFromContext(c)
|
|
||||||
list, count, err := qc.questionService.SearchList(ctx, Request, userID)
|
|
||||||
if err != nil {
|
|
||||||
handler.HandleResponse(c, err, nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
handler.HandleResponse(c, nil, gin.H{
|
|
||||||
"list": list,
|
|
||||||
"count": count,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddQuestion add question
|
// AddQuestion add question
|
||||||
// @Summary add question
|
// @Summary add question
|
||||||
// @Description add question
|
// @Description add question
|
||||||
// @Tags api-question
|
// @Tags Question
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
|
@ -309,7 +277,7 @@ func (qc *QuestionController) AddQuestion(ctx *gin.Context) {
|
||||||
// UpdateQuestion update question
|
// UpdateQuestion update question
|
||||||
// @Summary update question
|
// @Summary update question
|
||||||
// @Description update question
|
// @Description update question
|
||||||
// @Tags api-question
|
// @Tags Question
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
|
@ -366,7 +334,7 @@ func (qc *QuestionController) UpdateQuestion(ctx *gin.Context) {
|
||||||
// CloseMsgList close question msg list
|
// CloseMsgList close question msg list
|
||||||
// @Summary close question msg list
|
// @Summary close question msg list
|
||||||
// @Description close question msg list
|
// @Description close question msg list
|
||||||
// @Tags api-question
|
// @Tags Question
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
|
@ -380,7 +348,7 @@ func (qc *QuestionController) CloseMsgList(ctx *gin.Context) {
|
||||||
// SearchByTitleLike add question title like
|
// SearchByTitleLike add question title like
|
||||||
// @Summary add question title like
|
// @Summary add question title like
|
||||||
// @Description add question title like
|
// @Description add question title like
|
||||||
// @Tags api-question
|
// @Tags Question
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
|
@ -397,7 +365,7 @@ func (qc *QuestionController) SearchByTitleLike(ctx *gin.Context) {
|
||||||
// UserTop godoc
|
// UserTop godoc
|
||||||
// @Summary UserTop
|
// @Summary UserTop
|
||||||
// @Description UserTop
|
// @Description UserTop
|
||||||
// @Tags api-question
|
// @Tags Question
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
|
@ -417,7 +385,7 @@ func (qc *QuestionController) UserTop(ctx *gin.Context) {
|
||||||
// UserList godoc
|
// UserList godoc
|
||||||
// @Summary UserList
|
// @Summary UserList
|
||||||
// @Description UserList
|
// @Description UserList
|
||||||
// @Tags api-question
|
// @Tags Question
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
|
|
|
@ -91,8 +91,8 @@ func (tc *TemplateController) SiteInfo(ctx *gin.Context) *schema.TemplateSiteInf
|
||||||
|
|
||||||
// Index question list
|
// Index question list
|
||||||
func (tc *TemplateController) Index(ctx *gin.Context) {
|
func (tc *TemplateController) Index(ctx *gin.Context) {
|
||||||
req := &schema.QuestionSearch{
|
req := &schema.QuestionPageReq{
|
||||||
Order: "newest",
|
OrderCond: "newest",
|
||||||
}
|
}
|
||||||
if handler.BindAndCheck(ctx, req) {
|
if handler.BindAndCheck(ctx, req) {
|
||||||
tc.Page404(ctx)
|
tc.Page404(ctx)
|
||||||
|
@ -124,8 +124,8 @@ func (tc *TemplateController) Index(ctx *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *TemplateController) QuestionList(ctx *gin.Context) {
|
func (tc *TemplateController) QuestionList(ctx *gin.Context) {
|
||||||
req := &schema.QuestionSearch{
|
req := &schema.QuestionPageReq{
|
||||||
Order: "newest",
|
OrderCond: "newest",
|
||||||
}
|
}
|
||||||
if handler.BindAndCheck(ctx, req) {
|
if handler.BindAndCheck(ctx, req) {
|
||||||
tc.Page404(ctx)
|
tc.Page404(ctx)
|
||||||
|
|
|
@ -11,8 +11,8 @@ import (
|
||||||
"github.com/segmentfault/pacman/log"
|
"github.com/segmentfault/pacman/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (t *TemplateRenderController) Index(ctx *gin.Context, req *schema.QuestionSearch) ([]*schema.QuestionInfo, int64, error) {
|
func (t *TemplateRenderController) Index(ctx *gin.Context, req *schema.QuestionPageReq) ([]*schema.QuestionPageResp, int64, error) {
|
||||||
return t.questionService.SearchList(ctx, req, req.UserID)
|
return t.questionService.GetQuestionPage(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TemplateRenderController) QuestionDetail(ctx *gin.Context, id string) (resp *schema.QuestionInfo, err error) {
|
func (t *TemplateRenderController) QuestionDetail(ctx *gin.Context, id string) (resp *schema.QuestionInfo, err error) {
|
||||||
|
|
|
@ -15,19 +15,20 @@ func (q *TemplateRenderController) TagList(ctx context.Context, req *schema.GetT
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *TemplateRenderController) TagInfo(ctx context.Context, req *schema.GetTamplateTagInfoReq) (resp *schema.GetTagResp, questionList []*schema.QuestionInfo, questionCount int64, err error) {
|
func (q *TemplateRenderController) TagInfo(ctx context.Context, req *schema.GetTamplateTagInfoReq) (resp *schema.GetTagResp, questionList []*schema.QuestionPageResp, questionCount int64, err error) {
|
||||||
dto := &schema.GetTagInfoReq{}
|
dto := &schema.GetTagInfoReq{}
|
||||||
_ = copier.Copy(dto, req)
|
_ = copier.Copy(dto, req)
|
||||||
resp, err = q.tagService.GetTagInfo(ctx, dto)
|
resp, err = q.tagService.GetTagInfo(ctx, dto)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
searchQuestion := &schema.QuestionSearch{}
|
searchQuestion := &schema.QuestionPageReq{}
|
||||||
searchQuestion.Page = req.Page
|
searchQuestion.Page = req.Page
|
||||||
searchQuestion.PageSize = req.PageSize
|
searchQuestion.PageSize = req.PageSize
|
||||||
searchQuestion.Order = "newest"
|
searchQuestion.OrderCond = "newest"
|
||||||
searchQuestion.Tag = req.Name
|
searchQuestion.Tag = req.Name
|
||||||
questionList, questionCount, err = q.questionService.SearchList(ctx, searchQuestion, "")
|
searchQuestion.LoginUserID = req.UserID
|
||||||
|
questionList, questionCount, err = q.questionService.GetQuestionPage(ctx, searchQuestion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,11 +22,6 @@ var AdminQuestionSearchStatusIntToString = map[int]string{
|
||||||
QuestionStatusDeleted: "deleted",
|
QuestionStatusDeleted: "deleted",
|
||||||
}
|
}
|
||||||
|
|
||||||
type QuestionTag struct {
|
|
||||||
Question `xorm:"extends"`
|
|
||||||
TagRel `xorm:"extends"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Question question
|
// Question question
|
||||||
type Question struct {
|
type Question struct {
|
||||||
ID string `xorm:"not null pk BIGINT(20) id"`
|
ID string `xorm:"not null pk BIGINT(20) id"`
|
||||||
|
|
|
@ -205,70 +205,40 @@ func (qr *questionRepo) GetQuestionIDsPage(ctx context.Context, page, pageSize i
|
||||||
return questionIDList, nil
|
return questionIDList, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetQuestionPage get question page
|
// GetQuestionPage query question page
|
||||||
func (qr *questionRepo) GetQuestionPage(ctx context.Context, page, pageSize int, question *entity.Question) (questionList []*entity.Question, total int64, err error) {
|
func (qr *questionRepo) GetQuestionPage(ctx context.Context, page, pageSize int, userID, tagID, orderCond string) (
|
||||||
|
questionList []*entity.Question, total int64, err error) {
|
||||||
questionList = make([]*entity.Question, 0)
|
questionList = make([]*entity.Question, 0)
|
||||||
total, err = pager.Help(page, pageSize, questionList, question, qr.data.DB.NewSession())
|
|
||||||
if err != nil {
|
|
||||||
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// SearchList
|
session := qr.data.DB.Where("question.status = ? OR question.status = ?",
|
||||||
func (qr *questionRepo) SearchList(ctx context.Context, search *schema.QuestionSearch) ([]*entity.QuestionTag, int64, error) {
|
entity.QuestionStatusAvailable, entity.QuestionStatusClosed)
|
||||||
var count int64
|
if len(tagID) > 0 {
|
||||||
var err error
|
session.Join("LEFT", "tag_rel", "question.id = tag_rel.object_id")
|
||||||
rows := make([]*entity.QuestionTag, 0)
|
session.And("tag_rel.tag_id = ?", tagID)
|
||||||
if search.Page > 0 {
|
session.And("tag_rel.status = ?", entity.TagRelStatusAvailable)
|
||||||
search.Page = search.Page - 1
|
|
||||||
} else {
|
|
||||||
search.Page = 0
|
|
||||||
}
|
}
|
||||||
if search.PageSize == 0 {
|
if len(userID) > 0 {
|
||||||
search.PageSize = constant.DefaultPageSize
|
session.And("question.user_id = ?", userID)
|
||||||
}
|
}
|
||||||
offset := search.Page * search.PageSize
|
switch orderCond {
|
||||||
session := qr.data.DB.Table("question")
|
|
||||||
|
|
||||||
if len(search.TagIDs) > 0 {
|
|
||||||
session = session.Join("LEFT", "tag_rel", "question.id = tag_rel.object_id")
|
|
||||||
session = session.And("tag_rel.tag_id =?", search.TagIDs[0])
|
|
||||||
// session = session.In("tag_rel.tag_id ", search.TagIDs)
|
|
||||||
session = session.And("tag_rel.status =?", entity.TagRelStatusAvailable)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(search.UserID) > 0 {
|
|
||||||
session = session.And("question.user_id = ?", search.UserID)
|
|
||||||
}
|
|
||||||
|
|
||||||
session = session.In("question.status", []int{entity.QuestionStatusAvailable, entity.QuestionStatusClosed})
|
|
||||||
// if search.Status > 0 {
|
|
||||||
// session = session.And("question.status = ?", search.Status)
|
|
||||||
// }
|
|
||||||
// switch
|
|
||||||
// newest, active,frequent,score,unanswered
|
|
||||||
switch search.Order {
|
|
||||||
case "newest":
|
case "newest":
|
||||||
session = session.OrderBy("question.created_at desc")
|
session.OrderBy("question.created_at DESC")
|
||||||
case "active":
|
case "active":
|
||||||
session = session.OrderBy("question.post_update_time desc,question.updated_at desc")
|
session.OrderBy("question.post_update_time DESC, question.updated_at DESC")
|
||||||
case "frequent":
|
case "frequent":
|
||||||
session = session.OrderBy("question.view_count desc")
|
session.OrderBy("question.view_count DESC")
|
||||||
case "score":
|
case "score":
|
||||||
session = session.OrderBy("question.vote_count desc,question.view_count desc")
|
session.OrderBy("question.vote_count DESC, question.view_count DESC")
|
||||||
case "unanswered":
|
case "unanswered":
|
||||||
session = session.And("question.last_answer_id = 0")
|
session.Where("question.last_answer_id = 0")
|
||||||
session = session.OrderBy("question.created_at desc")
|
session.OrderBy("question.created_at DESC")
|
||||||
}
|
}
|
||||||
session = session.Limit(search.PageSize, offset)
|
|
||||||
session = session.Select("question.id,question.user_id,last_edit_user_id,question.title,question.original_text,question.parsed_text,question.status,question.view_count,question.unique_view_count,question.vote_count,question.answer_count,question.collection_count,question.follow_count,question.accepted_answer_id,question.last_answer_id,question.created_at,question.updated_at,question.post_update_time,question.revision_id")
|
total, err = pager.Help(page, pageSize, &questionList, &entity.Question{}, session)
|
||||||
count, err = session.FindAndCount(&rows)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
||||||
return rows, count, err
|
|
||||||
}
|
}
|
||||||
return rows, count, nil
|
return questionList, total, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qr *questionRepo) AdminSearchList(ctx context.Context, search *schema.AdminQuestionSearch) ([]*entity.Question, int64, error) {
|
func (qr *questionRepo) AdminSearchList(ctx context.Context, search *schema.AdminQuestionSearch) ([]*entity.Question, int64, error) {
|
||||||
|
|
|
@ -124,8 +124,7 @@ func (a *AnswerAPIRouter) RegisterUnAuthAnswerAPIRouter(r *gin.RouterGroup) {
|
||||||
|
|
||||||
//question
|
//question
|
||||||
r.GET("/question/info", a.questionController.GetQuestion)
|
r.GET("/question/info", a.questionController.GetQuestion)
|
||||||
r.POST("/question/search", a.questionController.SearchList)
|
r.GET("/question/page", a.questionController.QuestionPage)
|
||||||
r.GET("/question/page", a.questionController.Index)
|
|
||||||
r.GET("/question/similar/tag", a.questionController.SimilarQuestion)
|
r.GET("/question/similar/tag", a.questionController.SimilarQuestion)
|
||||||
r.GET("/personal/qa/top", a.questionController.UserTop)
|
r.GET("/personal/qa/top", a.questionController.UserTop)
|
||||||
r.GET("/personal/question/page", a.questionController.UserList)
|
r.GET("/personal/question/page", a.questionController.UserList)
|
||||||
|
@ -143,7 +142,6 @@ func (a *AnswerAPIRouter) RegisterUnAuthAnswerAPIRouter(r *gin.RouterGroup) {
|
||||||
r.GET("/tags/following", a.tagController.GetFollowingTags)
|
r.GET("/tags/following", a.tagController.GetFollowingTags)
|
||||||
r.GET("/tag", a.tagController.GetTagInfo)
|
r.GET("/tag", a.tagController.GetTagInfo)
|
||||||
r.GET("/tag/synonyms", a.tagController.GetTagSynonyms)
|
r.GET("/tag/synonyms", a.tagController.GetTagSynonyms)
|
||||||
r.GET("/question/index", a.questionController.Index)
|
|
||||||
|
|
||||||
//search
|
//search
|
||||||
r.GET("/search", a.searchController.Search)
|
r.GET("/search", a.searchController.Search)
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package schema
|
package schema
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/answerdev/answer/internal/base/validator"
|
"github.com/answerdev/answer/internal/base/validator"
|
||||||
"github.com/answerdev/answer/pkg/converter"
|
"github.com/answerdev/answer/pkg/converter"
|
||||||
)
|
)
|
||||||
|
@ -222,15 +224,66 @@ type UserQuestionInfo struct {
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type QuestionSearch struct {
|
const (
|
||||||
Page int `json:"page" form:"page"` // Query number of pages
|
QuestionOrderCondNewest = "newest"
|
||||||
PageSize int `json:"page_size" form:"page_size"` // Search page size
|
QuestionOrderCondActive = "active"
|
||||||
Order string `json:"order" form:"order"` // Search order by
|
QuestionOrderCondFrequent = "frequent"
|
||||||
// Tags []string `json:"tags" form:"tags"` // Search tag
|
QuestionOrderCondScore = "score"
|
||||||
Tag string `json:"tag" form:"tag"` //Search tag
|
QuestionOrderCondUnanswered = "unanswered"
|
||||||
TagIDs []string `json:"-" form:"-"` // Search tag
|
)
|
||||||
UserName string `json:"username" form:"username"` // Search username
|
|
||||||
UserID string `json:"-" form:"-"`
|
// QuestionPageReq query questions page
|
||||||
|
type QuestionPageReq struct {
|
||||||
|
Page int `validate:"omitempty,min=1" form:"page"`
|
||||||
|
PageSize int `validate:"omitempty,min=1" form:"page_size"`
|
||||||
|
OrderCond string `validate:"omitempty,oneof=newest active frequent score unanswered" form:"order"`
|
||||||
|
Tag string `validate:"omitempty,gt=0,lte=100" form:"tag"`
|
||||||
|
Username string `validate:"omitempty,gt=0,lte=100" form:"username"`
|
||||||
|
|
||||||
|
LoginUserID string `json:"-"`
|
||||||
|
UserIDBeSearched string `json:"-"`
|
||||||
|
TagID string `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
QuestionPageRespOperationTypeAsked = "question.operation_type.asked"
|
||||||
|
QuestionPageRespOperationTypeAnswered = "question.operation_type.answered"
|
||||||
|
QuestionPageRespOperationTypeModified = "question.operation_type.modified"
|
||||||
|
)
|
||||||
|
|
||||||
|
type QuestionPageResp struct {
|
||||||
|
ID string `json:"id" `
|
||||||
|
Title string `json:"title"`
|
||||||
|
UrlTitle string `json:"url_title"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Status int `json:"status"`
|
||||||
|
Tags []*TagResp `json:"tags"`
|
||||||
|
|
||||||
|
// question statistical information
|
||||||
|
ViewCount int `json:"view_count"`
|
||||||
|
UniqueViewCount int `json:"unique_view_count"`
|
||||||
|
VoteCount int `json:"vote_count"`
|
||||||
|
AnswerCount int `json:"answer_count"`
|
||||||
|
CollectionCount int `json:"collection_count"`
|
||||||
|
FollowCount int `json:"follow_count"`
|
||||||
|
|
||||||
|
// answer information
|
||||||
|
AcceptedAnswerID string `json:"accepted_answer_id"`
|
||||||
|
LastAnswerID string `json:"last_answer_id"`
|
||||||
|
LastAnsweredUserID string `json:"-"`
|
||||||
|
LastAnsweredAt time.Time `json:"-"`
|
||||||
|
|
||||||
|
// operator information
|
||||||
|
OperatedAt int64 `json:"operated_at"`
|
||||||
|
Operator *QuestionPageRespOperator `json:"operator"`
|
||||||
|
OperationType string `json:"operation_type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type QuestionPageRespOperator struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Rank int `json:"rank"`
|
||||||
|
DisplayName string `json:"display_name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AdminQuestionSearch struct {
|
type AdminQuestionSearch struct {
|
||||||
|
|
|
@ -73,7 +73,7 @@ func (ns *NotificationCommon) HandleNotification() {
|
||||||
|
|
||||||
// AddNotification
|
// AddNotification
|
||||||
// need set
|
// need set
|
||||||
// UserID
|
// LoginUserID
|
||||||
// Type 1 inbox 2 achievement
|
// Type 1 inbox 2 achievement
|
||||||
// [inbox] Activity
|
// [inbox] Activity
|
||||||
// [achievement] Rank
|
// [achievement] Rank
|
||||||
|
|
|
@ -6,11 +6,14 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/answerdev/answer/internal/base/constant"
|
"github.com/answerdev/answer/internal/base/constant"
|
||||||
|
"github.com/answerdev/answer/internal/base/handler"
|
||||||
"github.com/answerdev/answer/internal/base/reason"
|
"github.com/answerdev/answer/internal/base/reason"
|
||||||
|
"github.com/answerdev/answer/internal/base/translator"
|
||||||
"github.com/answerdev/answer/internal/service/activity_common"
|
"github.com/answerdev/answer/internal/service/activity_common"
|
||||||
"github.com/answerdev/answer/internal/service/activity_queue"
|
"github.com/answerdev/answer/internal/service/activity_queue"
|
||||||
"github.com/answerdev/answer/internal/service/config"
|
"github.com/answerdev/answer/internal/service/config"
|
||||||
"github.com/answerdev/answer/internal/service/meta"
|
"github.com/answerdev/answer/internal/service/meta"
|
||||||
|
"github.com/answerdev/answer/pkg/checker"
|
||||||
"github.com/answerdev/answer/pkg/htmltext"
|
"github.com/answerdev/answer/pkg/htmltext"
|
||||||
"github.com/segmentfault/pacman/errors"
|
"github.com/segmentfault/pacman/errors"
|
||||||
|
|
||||||
|
@ -30,8 +33,8 @@ type QuestionRepo interface {
|
||||||
UpdateQuestion(ctx context.Context, question *entity.Question, Cols []string) (err error)
|
UpdateQuestion(ctx context.Context, question *entity.Question, Cols []string) (err error)
|
||||||
GetQuestion(ctx context.Context, id string) (question *entity.Question, exist bool, err error)
|
GetQuestion(ctx context.Context, id string) (question *entity.Question, exist bool, err error)
|
||||||
GetQuestionList(ctx context.Context, question *entity.Question) (questions []*entity.Question, err error)
|
GetQuestionList(ctx context.Context, question *entity.Question) (questions []*entity.Question, err error)
|
||||||
GetQuestionPage(ctx context.Context, page, pageSize int, question *entity.Question) (questions []*entity.Question, total int64, err error)
|
GetQuestionPage(ctx context.Context, page, pageSize int, userID, tagID, orderCond string) (
|
||||||
SearchList(ctx context.Context, search *schema.QuestionSearch) ([]*entity.QuestionTag, int64, error)
|
questionList []*entity.Question, total int64, err error)
|
||||||
UpdateQuestionStatus(ctx context.Context, question *entity.Question) (err error)
|
UpdateQuestionStatus(ctx context.Context, question *entity.Question) (err error)
|
||||||
SearchByTitleLike(ctx context.Context, title string) (questionList []*entity.Question, err error)
|
SearchByTitleLike(ctx context.Context, title string) (questionList []*entity.Question, err error)
|
||||||
UpdatePvCount(ctx context.Context, questionID string) (err error)
|
UpdatePvCount(ctx context.Context, questionID string) (err error)
|
||||||
|
@ -126,21 +129,15 @@ func (qs *QuestionCommon) UpdataPostSetTime(ctx context.Context, questionID stri
|
||||||
|
|
||||||
func (qs *QuestionCommon) FindInfoByID(ctx context.Context, questionIDs []string, loginUserID string) (map[string]*schema.QuestionInfo, error) {
|
func (qs *QuestionCommon) FindInfoByID(ctx context.Context, questionIDs []string, loginUserID string) (map[string]*schema.QuestionInfo, error) {
|
||||||
list := make(map[string]*schema.QuestionInfo)
|
list := make(map[string]*schema.QuestionInfo)
|
||||||
listAddTag := make([]*entity.QuestionTag, 0)
|
|
||||||
questionList, err := qs.questionRepo.FindByID(ctx, questionIDs)
|
questionList, err := qs.questionRepo.FindByID(ctx, questionIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return list, err
|
return list, err
|
||||||
}
|
}
|
||||||
for _, item := range questionList {
|
questions, err := qs.FormatQuestions(ctx, questionList, loginUserID)
|
||||||
itemAddTag := &entity.QuestionTag{}
|
|
||||||
itemAddTag.Question = *item
|
|
||||||
listAddTag = append(listAddTag, itemAddTag)
|
|
||||||
}
|
|
||||||
QuestionInfo, err := qs.ListFormat(ctx, listAddTag, loginUserID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return list, err
|
return list, err
|
||||||
}
|
}
|
||||||
for _, item := range QuestionInfo {
|
for _, item := range questions {
|
||||||
list[item.ID] = item
|
list[item.ID] = item
|
||||||
}
|
}
|
||||||
return list, nil
|
return list, nil
|
||||||
|
@ -244,13 +241,114 @@ func (qs *QuestionCommon) Info(ctx context.Context, questionID string, loginUser
|
||||||
return showinfo, nil
|
return showinfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qs *QuestionCommon) ListFormat(ctx context.Context, questionList []*entity.QuestionTag, loginUserID string) ([]*schema.QuestionInfo, error) {
|
func (qs *QuestionCommon) FormatQuestionsPage(
|
||||||
|
ctx context.Context, questionList []*entity.Question, loginUserID string, orderCond string) (
|
||||||
|
formattedQuestions []*schema.QuestionPageResp, err error) {
|
||||||
|
language := handler.GetLangByCtx(ctx)
|
||||||
|
askedOp := translator.GlobalTrans.Tr(language, schema.QuestionPageRespOperationTypeAsked)
|
||||||
|
answeredOp := translator.GlobalTrans.Tr(language, schema.QuestionPageRespOperationTypeAnswered)
|
||||||
|
modifiedOp := translator.GlobalTrans.Tr(language, schema.QuestionPageRespOperationTypeModified)
|
||||||
|
|
||||||
|
formattedQuestions = make([]*schema.QuestionPageResp, 0)
|
||||||
|
|
||||||
|
questionIDs := make([]string, 0)
|
||||||
|
userIDs := make([]string, 0)
|
||||||
|
for _, questionInfo := range questionList {
|
||||||
|
t := &schema.QuestionPageResp{
|
||||||
|
ID: questionInfo.ID,
|
||||||
|
Title: questionInfo.Title,
|
||||||
|
UrlTitle: htmltext.UrlTitle(questionInfo.Title),
|
||||||
|
Description: htmltext.FetchExcerpt(questionInfo.ParsedText, "...", 240),
|
||||||
|
Status: questionInfo.Status,
|
||||||
|
ViewCount: questionInfo.ViewCount,
|
||||||
|
UniqueViewCount: questionInfo.UniqueViewCount,
|
||||||
|
VoteCount: questionInfo.VoteCount,
|
||||||
|
AnswerCount: questionInfo.AnswerCount,
|
||||||
|
CollectionCount: questionInfo.CollectionCount,
|
||||||
|
FollowCount: questionInfo.FollowCount,
|
||||||
|
AcceptedAnswerID: questionInfo.AcceptedAnswerID,
|
||||||
|
LastAnswerID: questionInfo.LastAnswerID,
|
||||||
|
}
|
||||||
|
|
||||||
|
questionIDs = append(questionIDs, questionInfo.ID)
|
||||||
|
userIDs = append(userIDs, questionInfo.UserID)
|
||||||
|
haveEdited, haveAnswered := false, false
|
||||||
|
if checker.IsNotZeroString(questionInfo.LastEditUserID) {
|
||||||
|
haveEdited = true
|
||||||
|
userIDs = append(userIDs, questionInfo.LastEditUserID)
|
||||||
|
}
|
||||||
|
if checker.IsNotZeroString(questionInfo.LastAnswerID) {
|
||||||
|
haveAnswered = true
|
||||||
|
|
||||||
|
answerInfo, exist, err := qs.answerRepo.GetAnswer(ctx, questionInfo.LastAnswerID)
|
||||||
|
if err == nil && exist {
|
||||||
|
if answerInfo.LastEditUserID != "0" {
|
||||||
|
t.LastAnsweredUserID = answerInfo.LastEditUserID
|
||||||
|
} else {
|
||||||
|
t.LastAnsweredUserID = answerInfo.UserID
|
||||||
|
}
|
||||||
|
t.LastAnsweredAt = answerInfo.CreatedAt
|
||||||
|
userIDs = append(userIDs, t.LastAnsweredUserID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if order condition is newest or nobody edited or nobody answered, only show question author
|
||||||
|
if orderCond == schema.QuestionOrderCondNewest || (!haveEdited && !haveAnswered) {
|
||||||
|
t.OperationType = askedOp
|
||||||
|
t.OperatedAt = questionInfo.CreatedAt.Unix()
|
||||||
|
t.Operator = &schema.QuestionPageRespOperator{ID: questionInfo.UserID}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no one
|
||||||
|
if haveEdited {
|
||||||
|
t.OperationType = modifiedOp
|
||||||
|
t.OperatedAt = questionInfo.UpdatedAt.Unix()
|
||||||
|
t.Operator = &schema.QuestionPageRespOperator{ID: questionInfo.LastEditUserID}
|
||||||
|
}
|
||||||
|
|
||||||
|
if haveAnswered {
|
||||||
|
if t.LastAnsweredAt.Unix() > t.OperatedAt {
|
||||||
|
t.OperationType = answeredOp
|
||||||
|
t.OperatedAt = t.LastAnsweredAt.Unix()
|
||||||
|
t.Operator = &schema.QuestionPageRespOperator{ID: t.LastAnsweredUserID}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
formattedQuestions = append(formattedQuestions, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
tagsMap, err := qs.tagCommon.BatchGetObjectTag(ctx, questionIDs)
|
||||||
|
if err != nil {
|
||||||
|
return formattedQuestions, err
|
||||||
|
}
|
||||||
|
userInfoMap, err := qs.userCommon.BatchUserBasicInfoByID(ctx, userIDs)
|
||||||
|
if err != nil {
|
||||||
|
return formattedQuestions, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range formattedQuestions {
|
||||||
|
tags, ok := tagsMap[item.ID]
|
||||||
|
if ok {
|
||||||
|
item.Tags = tags
|
||||||
|
} else {
|
||||||
|
item.Tags = make([]*schema.TagResp, 0)
|
||||||
|
}
|
||||||
|
userInfo := userInfoMap[item.Operator.ID]
|
||||||
|
if userInfo != nil {
|
||||||
|
item.Operator.DisplayName = userInfo.DisplayName
|
||||||
|
item.Operator.Username = userInfo.Username
|
||||||
|
item.Operator.Rank = userInfo.Rank
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return formattedQuestions, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (qs *QuestionCommon) FormatQuestions(ctx context.Context, questionList []*entity.Question, loginUserID string) ([]*schema.QuestionInfo, error) {
|
||||||
list := make([]*schema.QuestionInfo, 0)
|
list := make([]*schema.QuestionInfo, 0)
|
||||||
objectIds := make([]string, 0)
|
objectIds := make([]string, 0)
|
||||||
userIds := make([]string, 0)
|
userIds := make([]string, 0)
|
||||||
|
|
||||||
for _, questionInfo := range questionList {
|
for _, questionInfo := range questionList {
|
||||||
item := qs.ShowListFormat(ctx, questionInfo)
|
item := qs.ShowFormat(ctx, questionInfo)
|
||||||
list = append(list, item)
|
list = append(list, item)
|
||||||
objectIds = append(objectIds, item.ID)
|
objectIds = append(objectIds, item.ID)
|
||||||
userIds = append(userIds, item.UserID)
|
userIds = append(userIds, item.UserID)
|
||||||
|
@ -387,8 +485,8 @@ func (as *QuestionCommon) RemoveAnswer(ctx context.Context, id string) (err erro
|
||||||
return as.answerRepo.RemoveAnswer(ctx, id)
|
return as.answerRepo.RemoveAnswer(ctx, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qs *QuestionCommon) ShowListFormat(ctx context.Context, data *entity.QuestionTag) *schema.QuestionInfo {
|
func (qs *QuestionCommon) ShowListFormat(ctx context.Context, data *entity.Question) *schema.QuestionInfo {
|
||||||
return qs.ShowFormat(ctx, &data.Question)
|
return qs.ShowFormat(ctx, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qs *QuestionCommon) ShowFormat(ctx context.Context, data *entity.Question) *schema.QuestionInfo {
|
func (qs *QuestionCommon) ShowFormat(ctx context.Context, data *entity.Question) *schema.QuestionInfo {
|
||||||
|
|
|
@ -655,12 +655,13 @@ func (qs *QuestionService) SearchUserList(ctx context.Context, userName, order s
|
||||||
if !Exist {
|
if !Exist {
|
||||||
return userlist, 0, nil
|
return userlist, 0, nil
|
||||||
}
|
}
|
||||||
search := &schema.QuestionSearch{}
|
search := &schema.QuestionPageReq{}
|
||||||
search.Order = order
|
search.OrderCond = order
|
||||||
search.Page = page
|
search.Page = page
|
||||||
search.PageSize = pageSize
|
search.PageSize = pageSize
|
||||||
search.UserID = userinfo.ID
|
search.UserIDBeSearched = userinfo.ID
|
||||||
questionlist, count, err := qs.SearchList(ctx, search, loginUserID)
|
search.LoginUserID = loginUserID
|
||||||
|
questionlist, count, err := qs.GetQuestionPage(ctx, search)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return userlist, 0, err
|
return userlist, 0, err
|
||||||
}
|
}
|
||||||
|
@ -778,12 +779,13 @@ func (qs *QuestionService) SearchUserTopList(ctx context.Context, userName strin
|
||||||
if !Exist {
|
if !Exist {
|
||||||
return userQuestionlist, userAnswerlist, nil
|
return userQuestionlist, userAnswerlist, nil
|
||||||
}
|
}
|
||||||
search := &schema.QuestionSearch{}
|
search := &schema.QuestionPageReq{}
|
||||||
search.Order = "score"
|
search.OrderCond = "score"
|
||||||
search.Page = 0
|
search.Page = 0
|
||||||
search.PageSize = 5
|
search.PageSize = 5
|
||||||
search.UserID = userinfo.ID
|
search.UserIDBeSearched = userinfo.ID
|
||||||
questionlist, _, err := qs.SearchList(ctx, search, loginUserID)
|
search.LoginUserID = loginUserID
|
||||||
|
questionlist, _, err := qs.GetQuestionPage(ctx, search)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return userQuestionlist, userAnswerlist, err
|
return userQuestionlist, userAnswerlist, err
|
||||||
}
|
}
|
||||||
|
@ -858,57 +860,64 @@ func (qs *QuestionService) SearchByTitleLike(ctx context.Context, title string,
|
||||||
}
|
}
|
||||||
|
|
||||||
// SimilarQuestion
|
// SimilarQuestion
|
||||||
func (qs *QuestionService) SimilarQuestion(ctx context.Context, questionID string, loginUserID string) ([]*schema.QuestionInfo, int64, error) {
|
func (qs *QuestionService) SimilarQuestion(ctx context.Context, questionID string, loginUserID string) ([]*schema.QuestionPageResp, int64, error) {
|
||||||
list := make([]*schema.QuestionInfo, 0)
|
|
||||||
question, err := qs.questioncommon.Info(ctx, questionID, loginUserID)
|
question, err := qs.questioncommon.Info(ctx, questionID, loginUserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return list, 0, nil
|
return nil, 0, nil
|
||||||
}
|
}
|
||||||
tagNames := make([]string, 0, len(question.Tags))
|
tagNames := make([]string, 0, len(question.Tags))
|
||||||
for _, tag := range question.Tags {
|
for _, tag := range question.Tags {
|
||||||
tagNames = append(tagNames, tag.SlugName)
|
tagNames = append(tagNames, tag.SlugName)
|
||||||
}
|
}
|
||||||
search := &schema.QuestionSearch{}
|
search := &schema.QuestionPageReq{}
|
||||||
search.Order = "frequent"
|
search.OrderCond = "frequent"
|
||||||
search.Page = 0
|
search.Page = 0
|
||||||
search.PageSize = 6
|
search.PageSize = 6
|
||||||
if len(tagNames) > 0 {
|
if len(tagNames) > 0 {
|
||||||
search.Tag = tagNames[0]
|
search.Tag = tagNames[0]
|
||||||
}
|
}
|
||||||
return qs.SearchList(ctx, search, loginUserID)
|
search.LoginUserID = loginUserID
|
||||||
|
return qs.GetQuestionPage(ctx, search)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SearchList
|
// GetQuestionPage query questions page
|
||||||
func (qs *QuestionService) SearchList(ctx context.Context, req *schema.QuestionSearch, loginUserID string) ([]*schema.QuestionInfo, int64, error) {
|
func (qs *QuestionService) GetQuestionPage(ctx context.Context, req *schema.QuestionPageReq) (
|
||||||
|
questions []*schema.QuestionPageResp, total int64, err error) {
|
||||||
|
questions = make([]*schema.QuestionPageResp, 0)
|
||||||
|
|
||||||
|
// query by tag condition
|
||||||
if len(req.Tag) > 0 {
|
if len(req.Tag) > 0 {
|
||||||
tagInfo, has, err := qs.tagCommon.GetTagBySlugName(ctx, strings.ToLower(req.Tag))
|
tagInfo, exist, err := qs.tagCommon.GetTagBySlugName(ctx, strings.ToLower(req.Tag))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("tagCommon.GetTagListByNames error", err)
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
if has {
|
if exist {
|
||||||
req.TagIDs = append(req.TagIDs, tagInfo.ID)
|
req.TagID = tagInfo.ID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
list := make([]*schema.QuestionInfo, 0)
|
|
||||||
if req.UserName != "" {
|
// query by user condition
|
||||||
userinfo, exist, err := qs.userCommon.GetUserBasicInfoByUserName(ctx, req.UserName)
|
if req.Username != "" {
|
||||||
|
userinfo, exist, err := qs.userCommon.GetUserBasicInfoByUserName(ctx, req.Username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return list, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
if !exist {
|
if !exist {
|
||||||
return list, 0, err
|
return questions, 0, nil
|
||||||
}
|
}
|
||||||
req.UserID = userinfo.ID
|
req.UserIDBeSearched = userinfo.ID
|
||||||
}
|
}
|
||||||
questionList, count, err := qs.questionRepo.SearchList(ctx, req)
|
|
||||||
|
questionList, total, err := qs.questionRepo.GetQuestionPage(ctx, req.Page, req.PageSize,
|
||||||
|
req.UserIDBeSearched, req.TagID, req.OrderCond)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return list, count, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
list, err = qs.questioncommon.ListFormat(ctx, questionList, loginUserID)
|
questions, err = qs.questioncommon.FormatQuestionsPage(ctx, questionList, req.LoginUserID, req.OrderCond)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return list, count, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
return list, count, nil
|
return questions, total, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qs *QuestionService) AdminSetQuestionStatus(ctx context.Context, questionID string, setStatusStr string) error {
|
func (qs *QuestionService) AdminSetQuestionStatus(ctx context.Context, questionID string, setStatusStr string) error {
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
package checker
|
||||||
|
|
||||||
|
// IsNotZeroString check s is not empty string and is not "0"
|
||||||
|
func IsNotZeroString(s string) bool {
|
||||||
|
return len(s) > 0 && s != "0"
|
||||||
|
}
|
|
@ -25,31 +25,21 @@
|
||||||
>
|
>
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<div class="text-secondary me-1">
|
<div class="text-secondary me-1">
|
||||||
<a href="/users/{{.UserInfo.Username}}"
|
<a href="/users/{{.Operator.Username}}"
|
||||||
><span class="me-1 text-break"
|
><span class="me-1 text-break"
|
||||||
>{{.UserInfo.DisplayName}}</span
|
>{{.Operator.DisplayName}}</span
|
||||||
></a
|
></a
|
||||||
><span class="fw-bold" title="Reputation"
|
><span class="fw-bold" title="Reputation"
|
||||||
>{{.UserInfo.Rank}}</span
|
>{{.Operator.Rank}}</span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
• {{if eq .CreateTime .UpdateTime}}
|
|
||||||
<time
|
<time
|
||||||
class="text-secondary ms-1"
|
class="text-secondary ms-1"
|
||||||
datetime="{{timeFormatISO $.timezone .CreateTime}}"
|
datetime="{{timeFormatISO $.timezone .OperatedAt}}"
|
||||||
title="{{translatorTimeFormatLongDate $.language $.timezone .CreateTime}}"
|
title="{{translatorTimeFormatLongDate $.language $.timezone .OperatedAt}}"
|
||||||
>{{translator $.language "ui.question.asked"}}
|
>{{translator $.language "ui.question.asked"}}
|
||||||
{{translatorTimeFormat $.language $.timezone .CreateTime}}
|
{{translatorTimeFormat $.language $.timezone .OperatedAt}}
|
||||||
</time>
|
</time>
|
||||||
{{else if gt .UpdateTime 0}}
|
|
||||||
<time
|
|
||||||
class="text-secondary ms-1"
|
|
||||||
datetime="{{timeFormatISO $.timezone .UpdateTime}}"
|
|
||||||
title="{{translatorTimeFormatLongDate $.language $.timezone .UpdateTime}}"
|
|
||||||
>{{translator $.language "ui.question.modified"}}
|
|
||||||
{{translatorTimeFormat $.language $.timezone .UpdateTime}}
|
|
||||||
</time>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="ms-0 ms-md-3 mt-2 mt-md-0">
|
<div class="ms-0 ms-md-3 mt-2 mt-md-0">
|
||||||
<span
|
<span
|
||||||
|
|
Loading…
Reference in New Issue