diff --git a/api/controller/share.go b/api/controller/share.go index 2af5c4c..6efd8ec 100644 --- a/api/controller/share.go +++ b/api/controller/share.go @@ -1,22 +1,69 @@ package controller import ( + "fmt" "github.com/gin-gonic/gin" "knowledge/api/dao" "knowledge/api/dto" + "knowledge/api/model" "knowledge/api/requests" "knowledge/api/responses" + "knowledge/consts" "knowledge/global" "knowledge/utils" + "net/http" "time" ) type Share struct{} -// GetShare 获取分享数据 -func (r *Share) GetShare(c *gin.Context) { +// GetBackgroundImage 获取背景图 +func (r *Share) GetBackgroundImage(c *gin.Context) { shareRequest := requests.ShareRequest{} - req := shareRequest.GetShare + req := shareRequest.GetBackgroundImage + if err := c.ShouldBind(&req); err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + // 参数验证 + if err := global.Validate.Struct(req); err != nil { + responses.FailWithMessage(utils.Translate(err), c) + return + } + + questionQaDao := dao.QuestionQaDao{} + + // 获取题库数据 + maps := make(map[string]interface{}) + maps["qa_share_id"] = req.QaShareId + questionQa, err := questionQaDao.GetQuestionQa(maps) + if err != nil || questionQa == nil { + responses.FailWithMessage("题库不存在", c) + return + } + + if questionQa.QaStatus == 2 { + responses.FailWithMessage("题库已失效", c) + return + } + + // 检测过期时间 + now := time.Now() + qaExpireTime := time.Time(questionQa.QaExpireTime) + if qaExpireTime.Before(now) { + responses.FailWithMessage("题库已失效", c) + return + } + + image := utils.AddOssDomain(questionQa.Image) + responses.OkWithData(image, c) +} + +// ShareAuth 授权 +func (r *Share) ShareAuth(c *gin.Context) { + shareRequest := requests.ShareRequest{} + req := shareRequest.ShareAuth if err := c.ShouldBind(&req); err != nil { responses.FailWithMessage(err.Error(), c) return @@ -28,9 +75,7 @@ func (r *Share) GetShare(c *gin.Context) { return } - // 业务处理 questionQaDao := dao.QuestionQaDao{} - questionQaItemDao := dao.QuestionQaItemDao{} // 获取题库数据 maps := make(map[string]interface{}) @@ -59,47 +104,120 @@ func (r *Share) GetShare(c *gin.Context) { return } - //g := dto.ShareDto{} + token := &utils.Token{ + Client: 1, + QaId: fmt.Sprintf("%d", questionQa.QaId), + } + + // 生成jwt + ttl := 5 * time.Hour + jwt, err := token.NewJWT(ttl) + if err != nil { + responses.FailWithMessage("题库错误", c) + return + } + + // 处理返回值 + g := dto.ShareAuthDto{} + + g.Token = jwt + + responses.OkWithData(g, c) +} + +// GetQuestionQa 获取知识问答数据 +func (r *Share) GetQuestionQa(c *gin.Context) { + // 获取知识问答id + qaId := c.GetInt64("QaId") + if qaId == 0 { + c.JSON(http.StatusUnauthorized, gin.H{ + "message": "请输入密码后查看", + "code": consts.TokenError, + "data": "", + }) + return + } + + questionQaDao := dao.QuestionQaDao{} + + // 获取题库数据 + questionQa, err := questionQaDao.GetQuestionQaById(qaId) + if err != nil || questionQa == nil { + responses.FailWithMessage("题库不存在", c) + return + } + + if questionQa.QaStatus == 2 { + responses.FailWithMessage("题库已失效", c) + return + } + + // 检测过期时间 + now := time.Now() + qaExpireTime := time.Time(questionQa.QaExpireTime) + if qaExpireTime.Before(now) { + responses.FailWithMessage("题库已失效", c) + return + } + + g := dto.GetQuestionQaDto(questionQa) + + responses.OkWithData(g, c) +} + +// GetQuestion 获取题目数据 +func (r *Share) GetQuestion(c *gin.Context) { + // 获取知识问答id + qaId := c.GetInt64("QaId") + if qaId == 0 { + c.JSON(http.StatusUnauthorized, gin.H{ + "message": "请输入密码后查看", + "code": consts.TokenError, + "data": "", + }) + c.Abort() + return + } + + questionQaDao := dao.QuestionQaDao{} + questionQaItemDao := dao.QuestionQaItemDao{} + + // 获取题库数据 + questionQa, err := questionQaDao.GetQuestionQaById(qaId) + if err != nil || questionQa == nil { + responses.FailWithMessage("题库不存在", c) + return + } + + if questionQa.QaStatus == 2 { + responses.FailWithMessage("题库已失效", c) + return + } + + // 检测过期时间 + now := time.Now() + qaExpireTime := time.Time(questionQa.QaExpireTime) + if qaExpireTime.Before(now) { + responses.FailWithMessage("题库已失效", c) + return + } g := dto.ShareDto{ - QuestionQa: &dto.QuestionQaDto{}, Question: []*dto.QuestionDto{}, BaseTokenItem: []*dto.BaseTokenItemDto{}, } - // 加载题库数据 - g.QuestionQa = dto.GetQuestionQaDto(questionQa) + // 题目数据 + var questions []*model.QuestionQaItem // 题目数据-必备选中 - maps = make(map[string]interface{}) + maps := make(map[string]interface{}) maps["qa_id"] = questionQa.QaId maps["is_must_select"] = 1 questionQaItems, err := questionQaItemDao.GetQuestionQaItemPreloadList(maps) if err == nil && len(questionQaItems) > 0 { for _, item := range questionQaItems { - questionOptionDao := dao.QuestionOptionDao{} - maps = make(map[string]interface{}) - maps["question_id"] = item.QuestionId - questionOption, err := questionOptionDao.GetQuestionOptionList(maps) - if err != nil { - responses.FailWithMessage("内部错误", c) - return - } - - // 处理返回值 - questionDto := dto.GetShareQuestionDto(item.Question) - - // 加载选项 - questionDto.LoadQuestionOption(questionOption) - - // 加载图片 - questionDto.LoadQuestionImage(item.Question.QuestionImage) - - // 加载答案 - questionDto.LoadQuestionAnswer(item.Question.QuestionAnswer) - - // 将转换后的结构体添加到新切片中 - g.Question = append(g.Question, questionDto) + questions = append(questions, item) } } @@ -113,33 +231,37 @@ func (r *Share) GetShare(c *gin.Context) { questionQaItems, err = questionQaItemDao.GetQuestionQaItemWhereListRand(maps, remainingQuantity) if err == nil && len(questionQaItems) > 0 { for _, item := range questionQaItems { - questionOptionDao := dao.QuestionOptionDao{} - maps = make(map[string]interface{}) - maps["question_id"] = item.QuestionId - questionOption, err := questionOptionDao.GetQuestionOptionList(maps) - if err != nil { - responses.FailWithMessage("内部错误", c) - return - } - - // 处理返回值 - questionDto := dto.GetShareQuestionDto(item.Question) - - // 加载选项 - questionDto.LoadQuestionOption(questionOption) - - // 加载图片 - questionDto.LoadQuestionImage(item.Question.QuestionImage) - - // 加载答案 - questionDto.LoadQuestionAnswer(item.Question.QuestionAnswer) - - // 将转换后的结构体添加到新切片中 - g.Question = append(g.Question, questionDto) + questions = append(questions, item) } } } + for _, v := range questions { + questionOptionDao := dao.QuestionOptionDao{} + maps = make(map[string]interface{}) + maps["question_id"] = v.QuestionId + questionOption, err := questionOptionDao.GetQuestionOptionList(maps) + if err != nil { + responses.FailWithMessage("内部错误", c) + return + } + + // 处理返回值 + questionDto := dto.GetShareQuestionDto(v.Question) + + // 加载选项 + questionDto.LoadQuestionOptionSimplify(questionOption) + + // 加载图片 + questionDto.LoadQuestionImage(v.Question.QuestionImage) + + // 加载答案 + questionDto.LoadQuestionAnswer(v.Question) + + // 将转换后的结构体添加到新切片中 + g.Question = append(g.Question, questionDto) + } + // 按照难度重新排序题目顺序 //sort.SliceStable(g.Question, func(i, j int) bool { // return g.Question[i].Difficulty < g.Question[j].Difficulty diff --git a/api/dto/Question.go b/api/dto/Question.go index c7c1322..ea7c726 100644 --- a/api/dto/Question.go +++ b/api/dto/Question.go @@ -89,7 +89,7 @@ func GetQuestionListDto(m []*model.Question) []*QuestionDto { // 加载答案 if v.QuestionAnswer != "" { - response = response.LoadQuestionAnswer(v.QuestionAnswer) + response = response.LoadQuestionAnswer(v) } // 将转换后的结构体添加到新切片中 @@ -140,6 +140,14 @@ func (r *QuestionDto) LoadQuestionOption(m []*model.QuestionOption) *QuestionDto return r } +// LoadQuestionOptionSimplify 加载选项-简化 +func (r *QuestionDto) LoadQuestionOptionSimplify(m []*model.QuestionOption) *QuestionDto { + if len(m) > 0 { + r.QuestionOption = GetQuestionOptionSimplifyListDto(m) + } + return r +} + // LoadQuestionImage 加载图片 func (r *QuestionDto) LoadQuestionImage(s string) *QuestionDto { if s != "" { @@ -155,13 +163,17 @@ func (r *QuestionDto) LoadQuestionImage(s string) *QuestionDto { } // LoadQuestionAnswer 加载答案 -func (r *QuestionDto) LoadQuestionAnswer(s string) *QuestionDto { - if s != "" { - result := strings.Split(s, ",") - if len(result) > 0 { - for _, v := range result { - r.QuestionAnswer = append(r.QuestionAnswer, v) +func (r *QuestionDto) LoadQuestionAnswer(m *model.Question) *QuestionDto { + if m.QuestionAnswer != "" { + if m.QuestionType == 1 || m.QuestionType == 2 { + result := strings.Split(m.QuestionAnswer, ",") + if len(result) > 0 { + for _, v := range result { + r.QuestionAnswer = append(r.QuestionAnswer, v) + } } + } else { + r.QuestionAnswer[0] = m.QuestionAnswer } } return r diff --git a/api/dto/QuestionOption.go b/api/dto/QuestionOption.go index 287f6a9..2839306 100644 --- a/api/dto/QuestionOption.go +++ b/api/dto/QuestionOption.go @@ -49,3 +49,22 @@ func GetQuestionOptionListDto(m []*model.QuestionOption) []*QuestionOptionDto { return responses } + +// GetQuestionOptionSimplifyListDto 题目选项列表-简化 +func GetQuestionOptionSimplifyListDto(m []*model.QuestionOption) []*QuestionOptionDto { + // 处理返回值 + responses := make([]*QuestionOptionDto, len(m)) + + if len(m) > 0 { + for i, v := range m { + response := &QuestionOptionDto{ + OptionValue: v.OptionValue, + } + + // 将转换后的结构体添加到新切片中 + responses[i] = response + } + } + + return responses +} diff --git a/api/dto/QuestionQaItem.go b/api/dto/QuestionQaItem.go index c51d89d..d1df31a 100644 --- a/api/dto/QuestionQaItem.go +++ b/api/dto/QuestionQaItem.go @@ -94,7 +94,7 @@ func (r *QuestionQaItemDto) LoadQuestion(m *model.Question) *QuestionQaItemDto { r.Question = r.Question.LoadQuestionImage(m.QuestionImage) // 加载答案 - r.Question = r.Question.LoadQuestionAnswer(m.QuestionAnswer) + r.Question = r.Question.LoadQuestionAnswer(m) } return r } diff --git a/api/dto/Share.go b/api/dto/Share.go index c6a2fc7..e7f4703 100644 --- a/api/dto/Share.go +++ b/api/dto/Share.go @@ -1,7 +1,18 @@ package dto +// GetBackgroundImageDto 获取背景图 +type GetBackgroundImageDto struct { + Status int `json:"status"` // 状态 + Message string `json:"message"` // 提示信息 + Data interface{} `json:"data"` // 数据值 +} + +// ShareAuthDto 授权 +type ShareAuthDto struct { + Token string `json:"token"` // token +} + type ShareDto struct { - QuestionQa *QuestionQaDto `json:"question_qa"` // 题库数据 Question []*QuestionDto `json:"question"` // 题库关联题目列表 BaseTokenItem []*BaseTokenItemDto `json:"base_token_item"` // 题库关联飞花令-列表 } diff --git a/api/middlewares/auth.go b/api/middlewares/auth.go index f51e01f..947ae00 100644 --- a/api/middlewares/auth.go +++ b/api/middlewares/auth.go @@ -9,14 +9,6 @@ import ( // Auth Auth认证 func Auth() gin.HandlerFunc { return func(c *gin.Context) { - // 获取用户id - userId := c.GetInt64("UserId") - if userId == 0 { - responses.Fail(c) - c.Abort() - return - } - // 获取客户端 client := c.GetInt("Client") if client == 0 || (client != 1 && client != 2) { @@ -32,6 +24,14 @@ func Auth() gin.HandlerFunc { // 后台 if client == 2 { + // 获取用户id + userId := c.GetInt64("UserId") + if userId == 0 { + responses.Fail(c) + c.Abort() + return + } + adminUserDao := dao.AdminUserDao{} adminUser, err := adminUserDao.GetAdminUserFirstById(userId) if err != nil || adminUser == nil { diff --git a/api/middlewares/jwt.go b/api/middlewares/jwt.go index b412919..36e20ac 100644 --- a/api/middlewares/jwt.go +++ b/api/middlewares/jwt.go @@ -53,20 +53,41 @@ func Jwt() gin.HandlerFunc { return } - // 转换类型 - userId, err := strconv.ParseInt(t.UserId, 10, 64) - if err != nil { - c.JSON(http.StatusOK, gin.H{ - "message": "token错误", - "code": consts.TokenError, - "data": "", - }) + var userId int64 + var qaId int64 - c.Abort() - return + // 用户id + if t.UserId != "" { + userId, err = strconv.ParseInt(t.UserId, 10, 64) + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "message": "token错误", + "code": consts.TokenError, + "data": "", + }) + + c.Abort() + return + } + } + + // 知识问答id + if t.QaId != "" { + qaId, err = strconv.ParseInt(t.QaId, 10, 64) + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "message": "token错误", + "code": consts.TokenError, + "data": "", + }) + + c.Abort() + return + } } c.Set("UserId", userId) // 用户id + c.Set("QaId", qaId) // 知识问答id c.Set("Client", t.Client) // 客户端(1:前台 2:后台) c.Next() } diff --git a/api/requests/Share.go b/api/requests/Share.go index 20c61c8..dfa7f58 100644 --- a/api/requests/Share.go +++ b/api/requests/Share.go @@ -1,10 +1,17 @@ package requests type ShareRequest struct { - GetShare // 获取分享数据 + GetBackgroundImage // 获取背景图 + ShareAuth // 授权 } -type GetShare struct { +// GetBackgroundImage 获取背景图 +type GetBackgroundImage struct { + QaShareId string `json:"qa_share_id" form:"qa_share_id" label:"分享标识" validate:"required"` +} + +// ShareAuth 授权 +type ShareAuth struct { QaShareId string `json:"qa_share_id" form:"qa_share_id" label:"分享标识" validate:"required"` QaPassword string `json:"qa_password" form:"qa_password" label:"密码" validate:"required"` } diff --git a/api/router/router.go b/api/router/router.go index 33f9d53..48ec970 100644 --- a/api/router/router.go +++ b/api/router/router.go @@ -78,7 +78,14 @@ func publicRouter(r *gin.Engine, api controller.Api) { } // 获取分享数据 - r.GET("/share", api.Share.GetShare) + shareGroup := r.Group("/share") + { + // 获取背景图 + shareGroup.GET("/background", api.Share.GetBackgroundImage) + + // 授权 + shareGroup.POST("/auth", api.Share.ShareAuth) + } // 后台 adminGroup := r.Group("/admin") @@ -88,12 +95,6 @@ func publicRouter(r *gin.Engine, api controller.Api) { // 登陆 adminGroup.POST("/login", api.AdminUser.Login) - - // 新增题目 - adminGroup.POST("/question/test", api.Question.AddQuestionTest) - - // 修改题目 - adminGroup.PUT("/question/test/:question_id", api.Question.PutQuestionTest) } } @@ -221,4 +222,14 @@ func privateRouter(r *gin.Engine, api controller.Api) { staticGroup.GET("", api.Static.GetStatic) } } + + // 获取分享数据 + shareGroup := r.Group("/share") + { + // 获取知识问答数据 + shareGroup.GET("/qa", api.Share.GetQuestionQa) + + // 获取题目数据 + shareGroup.GET("/question", api.Share.GetQuestion) + } } diff --git a/api/service/AdminUser.go b/api/service/AdminUser.go index 29234e2..6000d3e 100644 --- a/api/service/AdminUser.go +++ b/api/service/AdminUser.go @@ -52,7 +52,7 @@ func (r *AdminUserService) Login(req requests.Login) (res *dto.AdminUserDto, err } // 生成jwt - jwt, err := token.NewJWT() + jwt, err := token.NewJWT(0) if err != nil { return nil, errors.New("登陆失败") } diff --git a/api/service/Question.go b/api/service/Question.go index bade4aa..3ada9b9 100644 --- a/api/service/Question.go +++ b/api/service/Question.go @@ -819,7 +819,7 @@ func (r *QuestionService) GetQuestion(questionId int64) (g *dto.QuestionDto, err g.LoadQuestionImage(question.QuestionImage) // 加载答案 - g.LoadQuestionAnswer(question.QuestionAnswer) + g.LoadQuestionAnswer(question) return g, nil } diff --git a/utils/jwt.go b/utils/jwt.go index 6efa9fb..8afa628 100644 --- a/utils/jwt.go +++ b/utils/jwt.go @@ -9,12 +9,15 @@ import ( type Token struct { UserId string `json:"user_id"` // 用户id Client int `json:"client"` // 客户端(1:前台 2:后台) + QaId string `json:"qa_id"` // 知识问答id jwt.RegisteredClaims // v5版本新加的方法 } // NewJWT GenerateJWT 生成JWT -func (t Token) NewJWT() (string, error) { - ttl := time.Duration(config.C.Jwt.Ttl) +func (t Token) NewJWT(ttl time.Duration) (string, error) { + if ttl == 0 { + ttl = time.Duration(config.C.Jwt.Ttl) + } t.RegisteredClaims.ExpiresAt = jwt.NewNumericDate(time.Now().Add(ttl * time.Hour)) // 过期时间24小时 t.RegisteredClaims.IssuedAt = jwt.NewNumericDate(time.Now()) // 签发时间