mirror of https://gitee.com/answerdev/answer.git
update question
This commit is contained in:
parent
219bc317d0
commit
2536703f32
|
@ -165,8 +165,8 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database,
|
|||
questionActivityRepo := activity.NewQuestionActivityRepo(dataData, activityRepo, userRankRepo)
|
||||
answerActivityService := activity2.NewAnswerActivityService(answerActivityRepo, questionActivityRepo)
|
||||
questionService := service.NewQuestionService(questionRepo, tagCommonService, questionCommon, userCommon, revisionService, metaService, collectionCommon, answerActivityService, dataData)
|
||||
questionController := controller.NewQuestionController(questionService, rankService)
|
||||
answerService := service.NewAnswerService(answerRepo, questionRepo, questionCommon, userCommon, collectionCommon, userRepo, revisionService, answerActivityService, answerCommon, voteRepo, emailService, userRoleRelService)
|
||||
questionController := controller.NewQuestionController(questionService, answerService, rankService)
|
||||
dashboardService := dashboard.NewDashboardService(questionRepo, answerRepo, commentCommonRepo, voteRepo, userRepo, reportRepo, configRepo, siteInfoCommonService, serviceConf, dataData)
|
||||
answerController := controller.NewAnswerController(answerService, rankService, dashboardService)
|
||||
searchParser := search_parser.NewSearchParser(tagCommonService, userCommon)
|
||||
|
|
74
docs/docs.go
74
docs/docs.go
|
@ -3063,6 +3063,45 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/answer/api/v1/question/answer": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "add question and answer",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Question"
|
||||
],
|
||||
"summary": "add question and answer",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "question",
|
||||
"name": "data",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/schema.QuestionAddByAnswer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/handler.RespBody"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/answer/api/v1/question/closemsglist": {
|
||||
"get": {
|
||||
"security": [
|
||||
|
@ -6751,6 +6790,41 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"schema.QuestionAddByAnswer": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"answer_content",
|
||||
"content",
|
||||
"tags",
|
||||
"title"
|
||||
],
|
||||
"properties": {
|
||||
"answer_content": {
|
||||
"type": "string",
|
||||
"maxLength": 65535,
|
||||
"minLength": 6
|
||||
},
|
||||
"content": {
|
||||
"description": "content",
|
||||
"type": "string",
|
||||
"maxLength": 65535,
|
||||
"minLength": 6
|
||||
},
|
||||
"tags": {
|
||||
"description": "tags",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/schema.TagItem"
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
"description": "question title",
|
||||
"type": "string",
|
||||
"maxLength": 150,
|
||||
"minLength": 6
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema.QuestionPageReq": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
@ -3051,6 +3051,45 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/answer/api/v1/question/answer": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "add question and answer",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Question"
|
||||
],
|
||||
"summary": "add question and answer",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "question",
|
||||
"name": "data",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/schema.QuestionAddByAnswer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/handler.RespBody"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/answer/api/v1/question/closemsglist": {
|
||||
"get": {
|
||||
"security": [
|
||||
|
@ -6739,6 +6778,41 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"schema.QuestionAddByAnswer": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"answer_content",
|
||||
"content",
|
||||
"tags",
|
||||
"title"
|
||||
],
|
||||
"properties": {
|
||||
"answer_content": {
|
||||
"type": "string",
|
||||
"maxLength": 65535,
|
||||
"minLength": 6
|
||||
},
|
||||
"content": {
|
||||
"description": "content",
|
||||
"type": "string",
|
||||
"maxLength": 65535,
|
||||
"minLength": 6
|
||||
},
|
||||
"tags": {
|
||||
"description": "tags",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/schema.TagItem"
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
"description": "question title",
|
||||
"type": "string",
|
||||
"maxLength": 150,
|
||||
"minLength": 6
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema.QuestionPageReq": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
@ -1019,6 +1019,33 @@ definitions:
|
|||
- tags
|
||||
- title
|
||||
type: object
|
||||
schema.QuestionAddByAnswer:
|
||||
properties:
|
||||
answer_content:
|
||||
maxLength: 65535
|
||||
minLength: 6
|
||||
type: string
|
||||
content:
|
||||
description: content
|
||||
maxLength: 65535
|
||||
minLength: 6
|
||||
type: string
|
||||
tags:
|
||||
description: tags
|
||||
items:
|
||||
$ref: '#/definitions/schema.TagItem'
|
||||
type: array
|
||||
title:
|
||||
description: question title
|
||||
maxLength: 150
|
||||
minLength: 6
|
||||
type: string
|
||||
required:
|
||||
- answer_content
|
||||
- content
|
||||
- tags
|
||||
- title
|
||||
type: object
|
||||
schema.QuestionPageReq:
|
||||
properties:
|
||||
orderCond:
|
||||
|
@ -3796,6 +3823,30 @@ paths:
|
|||
summary: update question
|
||||
tags:
|
||||
- Question
|
||||
/answer/api/v1/question/answer:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: add question and answer
|
||||
parameters:
|
||||
- description: question
|
||||
in: body
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/schema.QuestionAddByAnswer'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/handler.RespBody'
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: add question and answer
|
||||
tags:
|
||||
- Question
|
||||
/answer/api/v1/question/closemsglist:
|
||||
get:
|
||||
consumes:
|
||||
|
|
|
@ -138,7 +138,6 @@ func (ac *AnswerController) Add(ctx *gin.Context) {
|
|||
return
|
||||
}
|
||||
if !has {
|
||||
// todo !has
|
||||
handler.HandleResponse(ctx, nil, nil)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -14,18 +14,28 @@ import (
|
|||
"github.com/answerdev/answer/pkg/converter"
|
||||
"github.com/answerdev/answer/pkg/uid"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/jinzhu/copier"
|
||||
"github.com/segmentfault/pacman/errors"
|
||||
)
|
||||
|
||||
// QuestionController question controller
|
||||
type QuestionController struct {
|
||||
questionService *service.QuestionService
|
||||
answerService *service.AnswerService
|
||||
rankService *rank.RankService
|
||||
}
|
||||
|
||||
// NewQuestionController new controller
|
||||
func NewQuestionController(questionService *service.QuestionService, rankService *rank.RankService) *QuestionController {
|
||||
return &QuestionController{questionService: questionService, rankService: rankService}
|
||||
func NewQuestionController(
|
||||
questionService *service.QuestionService,
|
||||
answerService *service.AnswerService,
|
||||
rankService *rank.RankService,
|
||||
) *QuestionController {
|
||||
return &QuestionController{
|
||||
questionService: questionService,
|
||||
answerService: answerService,
|
||||
rankService: rankService,
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveQuestion delete question
|
||||
|
@ -281,6 +291,109 @@ func (qc *QuestionController) AddQuestion(ctx *gin.Context) {
|
|||
handler.HandleResponse(ctx, err, resp)
|
||||
}
|
||||
|
||||
// AddQuestionByAnswer add question
|
||||
// @Summary add question and answer
|
||||
// @Description add question and answer
|
||||
// @Tags Question
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security ApiKeyAuth
|
||||
// @Param data body schema.QuestionAddByAnswer true "question"
|
||||
// @Success 200 {object} handler.RespBody
|
||||
// @Router /answer/api/v1/question/answer [post]
|
||||
func (qc *QuestionController) AddQuestionByAnswer(ctx *gin.Context) {
|
||||
req := &schema.QuestionAddByAnswer{}
|
||||
errFields := handler.BindAndCheckReturnErr(ctx, req)
|
||||
if ctx.IsAborted() {
|
||||
return
|
||||
}
|
||||
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
|
||||
|
||||
canList, err := qc.rankService.CheckOperationPermissions(ctx, req.UserID, []string{
|
||||
permission.QuestionAdd,
|
||||
permission.QuestionEdit,
|
||||
permission.QuestionDelete,
|
||||
permission.QuestionClose,
|
||||
permission.QuestionReopen,
|
||||
permission.TagUseReservedTag,
|
||||
})
|
||||
if err != nil {
|
||||
handler.HandleResponse(ctx, err, nil)
|
||||
return
|
||||
}
|
||||
req.CanAdd = canList[0]
|
||||
req.CanEdit = canList[1]
|
||||
req.CanDelete = canList[2]
|
||||
req.CanClose = canList[3]
|
||||
req.CanReopen = canList[4]
|
||||
req.CanUseReservedTag = canList[5]
|
||||
if !req.CanAdd {
|
||||
handler.HandleResponse(ctx, errors.Forbidden(reason.RankFailToMeetTheCondition), nil)
|
||||
return
|
||||
}
|
||||
questionReq := new(schema.QuestionAdd)
|
||||
err = copier.Copy(questionReq, req)
|
||||
if err != nil {
|
||||
handler.HandleResponse(ctx, errors.Forbidden(reason.RequestFormatError), nil)
|
||||
return
|
||||
}
|
||||
errList, err := qc.questionService.CheckAddQuestion(ctx, questionReq)
|
||||
if err != nil {
|
||||
errlist, ok := errList.([]*validator.FormErrorField)
|
||||
if ok {
|
||||
errFields = append(errFields, errlist...)
|
||||
}
|
||||
}
|
||||
|
||||
if len(errFields) > 0 {
|
||||
handler.HandleResponse(ctx, errors.BadRequest(reason.RequestFormatError), errFields)
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := qc.questionService.AddQuestion(ctx, questionReq)
|
||||
if err != nil {
|
||||
errlist, ok := resp.([]*validator.FormErrorField)
|
||||
if ok {
|
||||
errFields = append(errFields, errlist...)
|
||||
}
|
||||
}
|
||||
|
||||
if len(errFields) > 0 {
|
||||
handler.HandleResponse(ctx, errors.BadRequest(reason.RequestFormatError), errFields)
|
||||
return
|
||||
}
|
||||
//add the question id to the answer
|
||||
questionInfo, ok := resp.(*schema.QuestionInfo)
|
||||
if ok {
|
||||
answerReq := &schema.AnswerAddReq{}
|
||||
answerReq.QuestionID = uid.DeShortID(questionInfo.ID)
|
||||
answerReq.UserID = middleware.GetLoginUserIDFromContext(ctx)
|
||||
answerReq.Content = req.AnswerContent
|
||||
answerReq.HTML = req.AnswerHTML
|
||||
answerID, err := qc.answerService.Insert(ctx, answerReq)
|
||||
if err != nil {
|
||||
handler.HandleResponse(ctx, err, nil)
|
||||
return
|
||||
}
|
||||
info, questionInfo, has, err := qc.answerService.Get(ctx, answerID, req.UserID)
|
||||
if err != nil {
|
||||
handler.HandleResponse(ctx, err, nil)
|
||||
return
|
||||
}
|
||||
if !has {
|
||||
handler.HandleResponse(ctx, nil, nil)
|
||||
return
|
||||
}
|
||||
handler.HandleResponse(ctx, err, gin.H{
|
||||
"info": info,
|
||||
"question": questionInfo,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
handler.HandleResponse(ctx, err, resp)
|
||||
}
|
||||
|
||||
// UpdateQuestion update question
|
||||
// @Summary update question
|
||||
// @Description update question
|
||||
|
|
|
@ -186,6 +186,7 @@ func (a *AnswerAPIRouter) RegisterAnswerAPIRouter(r *gin.RouterGroup) {
|
|||
|
||||
// question
|
||||
r.POST("/question", a.questionController.AddQuestion)
|
||||
r.POST("/question/answer", a.questionController.AddQuestionByAnswer)
|
||||
r.PUT("/question", a.questionController.UpdateQuestion)
|
||||
r.DELETE("/question", a.questionController.RemoveQuestion)
|
||||
r.PUT("/question/status", a.questionController.CloseQuestion)
|
||||
|
|
|
@ -63,6 +63,33 @@ func (req *QuestionAdd) Check() (errFields []*validator.FormErrorField, err erro
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
type QuestionAddByAnswer struct {
|
||||
// question title
|
||||
Title string `validate:"required,notblank,gte=6,lte=150" json:"title"`
|
||||
// content
|
||||
Content string `validate:"required,notblank,gte=6,lte=65535" json:"content"`
|
||||
// html
|
||||
HTML string `json:"-"`
|
||||
AnswerContent string `validate:"required,notblank,gte=6,lte=65535" json:"answer_content"`
|
||||
AnswerHTML string `json:"-"`
|
||||
// tags
|
||||
Tags []*TagItem `validate:"required,dive" json:"tags"`
|
||||
// user id
|
||||
UserID string `json:"-"`
|
||||
QuestionPermission
|
||||
}
|
||||
|
||||
func (req *QuestionAddByAnswer) Check() (errFields []*validator.FormErrorField, err error) {
|
||||
req.HTML = converter.Markdown2HTML(req.Content)
|
||||
req.AnswerHTML = converter.Markdown2HTML(req.AnswerContent)
|
||||
for _, tag := range req.Tags {
|
||||
if len(tag.OriginalText) > 0 {
|
||||
tag.ParsedText = converter.Markdown2HTML(tag.OriginalText)
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type QuestionPermission struct {
|
||||
// whether user can add it
|
||||
CanAdd bool `json:"-"`
|
||||
|
|
|
@ -20,7 +20,6 @@ import (
|
|||
"github.com/answerdev/answer/pkg/encryption"
|
||||
"github.com/answerdev/answer/pkg/htmltext"
|
||||
"github.com/answerdev/answer/pkg/uid"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/jinzhu/copier"
|
||||
"github.com/segmentfault/pacman/errors"
|
||||
"github.com/segmentfault/pacman/log"
|
||||
|
|
Loading…
Reference in New Issue