knowledge-api/api/service/Question.go

944 lines
22 KiB
Go

package service
import (
"errors"
"fmt"
"gorm.io/gorm"
"knowledge/api/dao"
"knowledge/api/dto"
"knowledge/api/model"
"knowledge/api/requests"
"knowledge/global"
"knowledge/utils"
"strconv"
"strings"
"time"
)
type QuestionService struct {
}
// AddQuestion 新增题目
func (r *QuestionService) AddQuestion(req requests.AddQuestion) (bool, error) {
// 验证一级标签
firstLabelId, err := strconv.ParseInt(req.FirstLabelId, 10, 64)
if err != nil {
return false, err
}
labelDao := dao.LabelDao{}
_, err = labelDao.GetLabelFirstById(firstLabelId)
if err != nil {
return false, err
}
// 验证二级标签
var secondLabelId int64
if req.SecondLabelId != "" {
secondLabelId, err = strconv.ParseInt(req.SecondLabelId, 10, 64)
if err != nil {
return false, err
}
_, err = labelDao.GetLabelFirstById(secondLabelId)
if err != nil {
return false, err
}
}
// 处理图片
var questionImage string
if len(req.QuestionImage) > 0 {
result := make([]string, len(req.QuestionImage))
for i, url := range req.QuestionImage {
result[i] = utils.RemoveOssDomain(url)
}
questionImage = strings.Join(result, ",")
}
// 处理答案
var questionAnswer string
if len(req.QuestionAnswer) > 0 {
result := make([]string, len(req.QuestionAnswer))
for i, url := range req.QuestionAnswer {
result[i] = url
}
questionAnswer = strings.Join(result, ",")
}
// 判断选项
if req.QuestionType == 1 || req.QuestionType == 2 {
if len(req.QuestionOption) == 0 {
return false, errors.New("请填入选项")
}
questionOption := "A.B.C.D.E.F.G.H.I.J.K."
for _, option := range req.QuestionOption {
if option == "" {
return false, errors.New("存在为空的选项")
}
// 取出首字母
s := option[0:1]
// 判断是否为正常选项
if !strings.Contains(questionOption, s) {
return false, errors.New("请正确输入选项序号")
}
}
// 判断答案是否在选项中
for _, s := range req.QuestionAnswer {
isExist := false
for _, s2 := range req.QuestionOption {
if strings.Contains(s2, s) {
isExist = true
}
}
if isExist == false {
return false, errors.New("答案不在选项中,请重新填写")
}
}
}
// 验证重复
if req.QuestionSource == 1 {
questionDao := dao.QuestionDao{}
maps := make(map[string]interface{})
maps["question_name"] = req.QuestionName
question, _ := questionDao.GetQuestion(maps)
if question != nil {
return false, errors.New("题目名称重复")
}
}
// 开始事务
tx := global.Db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
questionDao := dao.QuestionDao{}
// 新增题目
question := &model.Question{
QuestionName: req.QuestionName,
QuestionType: req.QuestionType,
QuestionStatus: req.QuestionStatus,
QuestionSource: req.QuestionSource,
QuestionImage: questionImage,
QuestionAnswer: questionAnswer,
QuestionAnalysis: req.QuestionAnalysis,
Difficulty: req.Difficulty,
FirstLabelId: &firstLabelId,
SecondLabelId: nil,
}
if req.SecondLabelId != "" {
question.SecondLabelId = &secondLabelId
}
question, err = questionDao.AddQuestion(tx, question)
if err != nil {
tx.Rollback()
return false, errors.New("新增失败")
}
// 新增选项
questionOptionDao := dao.QuestionOptionDao{}
for _, s := range req.QuestionOption {
questionOption := &model.QuestionOption{
QuestionId: question.QuestionId,
OptionValue: s,
}
questionOption, err := questionOptionDao.AddQuestionOption(tx, questionOption)
if err != nil {
tx.Rollback()
return false, errors.New("新增失败")
}
}
// 处理题库数据
if req.QaId != "" {
qaId, err := strconv.ParseInt(req.QaId, 10, 64)
if err != nil {
tx.Rollback()
return false, err
}
// 获取题库数据
questionQaDao := dao.QuestionQaDao{}
questionQa, err := questionQaDao.GetQuestionQaById(qaId)
if err != nil {
tx.Rollback()
return false, err
}
if questionQa.QaStatus == 2 {
tx.Rollback()
return false, errors.New("题库已失效")
}
qaExpireTime := time.Time(questionQa.QaExpireTime)
if qaExpireTime.Before(time.Now()) {
tx.Rollback()
return false, errors.New("题库已过期")
}
// 新增题库明细
questionQaItemDao := dao.QuestionQaItemDao{}
questionQaItem := &model.QuestionQaItem{
QaId: qaId,
QuestionId: question.QuestionId,
IsMustSelect: 0,
}
_, err = questionQaItemDao.AddQuestionQaItem(tx, questionQaItem)
if err != nil {
tx.Rollback()
return false, err
}
}
tx.Commit()
return true, nil
}
// AddQuestionTest 新增题目
func (r *QuestionService) AddQuestionTest(req requests.AddQuestionTest) (bool, error) {
// 验证一级标签
firstLabelId, err := strconv.ParseInt(req.FirstLabelId, 10, 64)
if err != nil {
return false, err
}
labelDao := dao.LabelDao{}
_, err = labelDao.GetLabelFirstById(firstLabelId)
if err != nil {
return false, err
}
// 验证二级标签
var secondLabelId int64
if req.SecondLabelId != "" {
secondLabelId, err = strconv.ParseInt(req.SecondLabelId, 10, 64)
if err != nil {
return false, err
}
_, err = labelDao.GetLabelFirstById(secondLabelId)
if err != nil {
return false, err
}
}
// 处理图片
var questionImage string
if req.QuestionImage != nil {
questionImage = *req.QuestionImage
if strings.HasSuffix(questionImage, "|") {
questionImage = questionImage[:len(questionImage)-1]
}
if strings.HasSuffix(questionImage, "|") {
questionImage = questionImage[:len(questionImage)-1]
}
questionImages := strings.Split(questionImage, "|")
if len(questionImages) > 0 {
result := make([]string, len(questionImages))
for i, url := range questionImages {
result[i] = utils.RemoveOssDomain(url)
}
questionImage = strings.Join(result, ",")
}
}
// 判断选项
if req.QuestionType == 1 || req.QuestionType == 2 {
if req.Input1 == nil {
return false, errors.New("请填入选项")
}
}
// 验证重复
questionDao := dao.QuestionDao{}
maps := make(map[string]interface{})
maps["question_name"] = req.QuestionName
question, _ := questionDao.GetQuestion(maps)
if question != nil {
return false, errors.New("题目名称重复")
}
questionStatus, err := strconv.Atoi(req.QuestionStatus)
if err != nil {
return false, errors.New("题目状态错误")
}
difficulty, err := strconv.Atoi(req.Difficulty)
if err != nil {
return false, errors.New("题目难度错误")
}
// 开始事务
tx := global.Db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
// 新增题目
question = &model.Question{
QuestionName: req.QuestionName,
QuestionType: req.QuestionType,
QuestionStatus: questionStatus,
QuestionSource: 1,
QuestionImage: questionImage,
QuestionAnswer: req.QuestionAnswer,
QuestionAnalysis: req.QuestionAnalysis,
Difficulty: difficulty,
FirstLabelId: &firstLabelId,
SecondLabelId: nil,
}
if req.SecondLabelId != "" {
question.SecondLabelId = &secondLabelId
}
question, err = questionDao.AddQuestion(tx, question)
if err != nil {
tx.Rollback()
return false, errors.New("新增失败")
}
// 新增选项
questionOptionDao := dao.QuestionOptionDao{}
if req.QuestionType == 1 || req.QuestionType == 2 {
if req.Input1 != nil {
questionOption := &model.QuestionOption{
QuestionId: question.QuestionId,
OptionValue: *req.Input1,
}
questionOption, err := questionOptionDao.AddQuestionOption(tx, questionOption)
if err != nil {
tx.Rollback()
return false, errors.New("新增失败")
}
}
if req.Input2 != nil {
questionOption := &model.QuestionOption{
QuestionId: question.QuestionId,
OptionValue: *req.Input2,
}
questionOption, err := questionOptionDao.AddQuestionOption(tx, questionOption)
if err != nil {
tx.Rollback()
return false, errors.New("新增失败")
}
}
if req.Input3 != nil {
questionOption := &model.QuestionOption{
QuestionId: question.QuestionId,
OptionValue: *req.Input3,
}
questionOption, err := questionOptionDao.AddQuestionOption(tx, questionOption)
if err != nil {
tx.Rollback()
return false, errors.New("新增失败")
}
}
if req.Input4 != nil {
questionOption := &model.QuestionOption{
QuestionId: question.QuestionId,
OptionValue: *req.Input4,
}
questionOption, err := questionOptionDao.AddQuestionOption(tx, questionOption)
if err != nil {
tx.Rollback()
return false, errors.New("新增失败")
}
}
if req.Input5 != nil {
questionOption := &model.QuestionOption{
QuestionId: question.QuestionId,
OptionValue: *req.Input5,
}
questionOption, err := questionOptionDao.AddQuestionOption(tx, questionOption)
if err != nil {
tx.Rollback()
return false, errors.New("新增失败")
}
}
}
tx.Commit()
return true, nil
}
// PutQuestion 修改题目
func (r *QuestionService) PutQuestion(questionId int64, req requests.PutQuestion) (bool, error) {
questionDao := dao.QuestionDao{}
question, err := questionDao.GetQuestionById(questionId)
if err != nil {
return false, errors.New("题目不存在")
}
// 开始事务
tx := global.Db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
questionData := make(map[string]interface{})
// 题目名称
if req.QuestionName != question.QuestionName {
questionData["question_name"] = req.QuestionName
}
// 题目类型
if req.QuestionType != question.QuestionType {
questionData["question_type"] = req.QuestionType
}
// 状态
if req.QuestionStatus != question.QuestionStatus {
questionData["question_status"] = req.QuestionStatus
}
// 解析
if req.QuestionAnalysis != question.QuestionAnalysis {
questionData["question_analysis"] = req.QuestionAnalysis
}
// 难度
if req.Difficulty != question.Difficulty {
questionData["difficulty"] = req.Difficulty
}
// 验证一级标签
firstLabelId, err := strconv.ParseInt(req.FirstLabelId, 10, 64)
if err != nil {
return false, err
}
if question.FirstLabelId == nil {
questionData["first_label_id"] = firstLabelId
} else {
if firstLabelId != *question.FirstLabelId {
labelDao := dao.LabelDao{}
_, err = labelDao.GetLabelFirstById(firstLabelId)
if err != nil {
return false, err
}
questionData["first_label_id"] = firstLabelId
}
}
// 验证二级标签
if req.SecondLabelId == "" {
if question.SecondLabelId != nil {
questionData["second_label_id"] = gorm.Expr("NULL")
}
} else {
// 验证二级标签
if req.SecondLabelId != "" {
secondLabelId, err := strconv.ParseInt(req.SecondLabelId, 10, 64)
if err != nil {
return false, err
}
if &secondLabelId != question.SecondLabelId {
labelDao := dao.LabelDao{}
_, err = labelDao.GetLabelFirstById(secondLabelId)
if err != nil {
return false, err
}
questionData["second_label_id"] = secondLabelId
}
}
}
// 图片
if len(req.QuestionImage) > 0 {
result := make([]string, len(req.QuestionImage))
for i, url := range req.QuestionImage {
result[i] = utils.RemoveOssDomain(url)
}
questionData["question_image"] = strings.Join(result, ",")
} else {
questionData["question_image"] = nil
}
// 答案
questionAnswer := make([]string, len(req.QuestionAnswer))
for i, v := range req.QuestionAnswer {
questionAnswer[i] = v
}
questionData["question_answer"] = strings.Join(questionAnswer, ",")
// 判断选项
if req.QuestionType == 1 || req.QuestionType == 2 {
if len(req.QuestionOption) == 0 {
tx.Rollback()
return false, errors.New("请填入选项")
}
questionOption := "ABCDEFGHIJK"
for _, option := range req.QuestionOption {
if option == "" {
tx.Rollback()
return false, errors.New("存在为空的选项")
}
if option == "," {
tx.Rollback()
return false, errors.New("存在为空的选项")
}
// 取出选项首字母
s := option[0:1]
// 判断是否为正常选项
if !strings.Contains(questionOption, s) {
tx.Rollback()
return false, errors.New("请正确输入选项序号")
}
}
// 判断答案是否在选项中
for _, s := range req.QuestionAnswer {
isExist := false
for _, s2 := range req.QuestionOption {
if strings.Contains(s2, s) {
isExist = true
}
}
if isExist == false {
tx.Rollback()
return false, errors.New("答案不在选项中,请重新填写")
}
}
}
// 验证重复
if req.QuestionName != question.QuestionName {
maps := make(map[string]interface{})
maps["question_name"] = req.QuestionName
res, _ := questionDao.GetQuestion(maps)
if res != nil {
tx.Rollback()
return false, errors.New("题目名称重复")
}
}
// 删除所有选项
if question.QuestionType == 1 || question.QuestionType == 2 {
questionOptionDao := dao.QuestionOptionDao{}
err = questionOptionDao.DeleteQuestionOptionByQuestionId(tx, question.QuestionId)
if err != nil {
tx.Rollback()
return false, errors.New(err.Error())
}
}
if req.QuestionType == 1 || req.QuestionType == 2 {
// 新增选项
questionOptionDao := dao.QuestionOptionDao{}
for _, s := range req.QuestionOption {
questionOption := &model.QuestionOption{
QuestionId: question.QuestionId,
OptionValue: s,
}
questionOption, err := questionOptionDao.AddQuestionOption(tx, questionOption)
if err != nil {
tx.Rollback()
return false, errors.New("修改失败")
}
}
}
err = questionDao.EditQuestionById(tx, question.QuestionId, questionData)
if err != nil {
tx.Rollback()
return false, errors.New(err.Error())
}
tx.Commit()
return true, nil
}
// PutQuestionTest 修改题目
func (r *QuestionService) PutQuestionTest(questionId int64, req requests.PutQuestionTest) (bool, error) {
questionDao := dao.QuestionDao{}
question, err := questionDao.GetQuestionById(questionId)
if err != nil {
return false, errors.New("题目不存在")
}
// 开始事务
tx := global.Db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
fmt.Println(r)
}
}()
questionData := make(map[string]interface{})
// 题目名称
if req.QuestionName != question.QuestionName {
questionData["question_name"] = req.QuestionName
}
// 题目类型
if req.QuestionType != "" {
questionType, err := strconv.Atoi(req.QuestionType)
if err != nil {
tx.Rollback()
return false, errors.New("题目类型错误")
}
if questionType != question.QuestionType {
questionData["question_type"] = req.QuestionType
}
}
// 状态
if req.QuestionStatus != "" {
questionStatus, err := strconv.Atoi(req.QuestionStatus)
if err != nil {
tx.Rollback()
return false, errors.New("题目状态错误")
}
if questionStatus != question.QuestionStatus {
questionData["question_status"] = req.QuestionStatus
}
}
// 答案
if req.QuestionAnswer != question.QuestionAnswer {
questionData["question_answer"] = req.QuestionAnswer
}
// 解析
if req.QuestionAnalysis != question.QuestionAnalysis {
questionData["question_analysis"] = req.QuestionAnalysis
}
// 难度
if req.Difficulty != "" {
difficulty, err := strconv.Atoi(req.Difficulty)
if err != nil {
tx.Rollback()
return false, errors.New("题目难度错误")
}
if difficulty != question.Difficulty {
questionData["difficulty"] = req.Difficulty
}
}
// 验证一级标签
firstLabelId, err := strconv.ParseInt(req.FirstLabelId, 10, 64)
if err != nil {
tx.Rollback()
return false, err
}
if &firstLabelId != question.FirstLabelId {
labelDao := dao.LabelDao{}
_, err = labelDao.GetLabelFirstById(firstLabelId)
if err != nil {
tx.Rollback()
return false, err
}
questionData["first_label_id"] = firstLabelId
}
// 验证二级标签
if req.SecondLabelId == "" {
if question.SecondLabelId != nil {
questionData["second_label_id"] = gorm.Expr("NULL")
}
} else {
// 验证二级标签
if req.SecondLabelId != "" {
secondLabelId, err := strconv.ParseInt(req.SecondLabelId, 10, 64)
if err != nil {
tx.Rollback()
return false, err
}
if &secondLabelId != question.SecondLabelId {
labelDao := dao.LabelDao{}
_, err := labelDao.GetLabelFirstById(secondLabelId)
if err != nil {
tx.Rollback()
return false, err
}
questionData["second_label_id"] = secondLabelId
}
}
}
// 图片
if req.QuestionImage != nil {
questionImage := *req.QuestionImage
if strings.HasSuffix(questionImage, "|") {
questionImage = questionImage[:len(questionImage)-1]
}
if strings.HasSuffix(questionImage, ",") {
questionImage = questionImage[:len(questionImage)-1]
}
questionImages := strings.Split(questionImage, "|")
if len(questionImages) > 0 {
result := make([]string, len(questionImages))
for i, url := range questionImages {
result[i] = utils.RemoveOssDomain(url)
}
questionImage = strings.Join(result, ",")
if questionImage != question.QuestionImage {
questionData["question_image"] = questionImage
}
}
}
// 验证重复
if req.QuestionName != question.QuestionName {
maps := make(map[string]interface{})
maps["question_name"] = req.QuestionName
res, _ := questionDao.GetQuestion(maps)
if res != nil {
tx.Rollback()
return false, errors.New("题目名称重复")
}
}
// 删除所有选项
if question.QuestionType == 1 || question.QuestionType == 2 {
questionOptionDao := dao.QuestionOptionDao{}
err = questionOptionDao.DeleteQuestionOptionByQuestionId(tx, question.QuestionId)
if err != nil {
tx.Rollback()
return false, errors.New(err.Error())
}
}
if req.QuestionType == "1" || req.QuestionType == "2" {
// 新增选项
questionOptionDao := dao.QuestionOptionDao{}
if req.Input1 != nil {
questionOption := &model.QuestionOption{
QuestionId: question.QuestionId,
OptionValue: *req.Input1,
}
questionOption, err := questionOptionDao.AddQuestionOption(tx, questionOption)
if err != nil {
tx.Rollback()
return false, errors.New("修改失败")
}
}
if req.Input2 != nil {
questionOption := &model.QuestionOption{
QuestionId: question.QuestionId,
OptionValue: *req.Input2,
}
questionOption, err := questionOptionDao.AddQuestionOption(tx, questionOption)
if err != nil {
tx.Rollback()
return false, errors.New("修改失败")
}
}
if req.Input3 != nil {
questionOption := &model.QuestionOption{
QuestionId: question.QuestionId,
OptionValue: *req.Input3,
}
questionOption, err := questionOptionDao.AddQuestionOption(tx, questionOption)
if err != nil {
tx.Rollback()
return false, errors.New("修改失败")
}
}
if req.Input4 != nil {
questionOption := &model.QuestionOption{
QuestionId: question.QuestionId,
OptionValue: *req.Input4,
}
questionOption, err := questionOptionDao.AddQuestionOption(tx, questionOption)
if err != nil {
tx.Rollback()
return false, errors.New("修改失败")
}
}
if req.Input5 != nil {
questionOption := &model.QuestionOption{
QuestionId: question.QuestionId,
OptionValue: *req.Input5,
}
questionOption, err := questionOptionDao.AddQuestionOption(tx, questionOption)
if err != nil {
tx.Rollback()
return false, errors.New("修改失败")
}
}
}
err = questionDao.EditQuestionById(tx, question.QuestionId, questionData)
if err != nil {
tx.Rollback()
return false, errors.New(err.Error())
}
tx.Commit()
return true, nil
}
// DeleteQuestion 删除题目
func (r *QuestionService) DeleteQuestion(req requests.DeleteQuestion) (bool, error) {
questionDao := dao.QuestionDao{}
questionOptionDao := dao.QuestionOptionDao{}
// 开始事务
tx := global.Db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
for _, questionId := range req.QuestionId {
// 将字符串转换为int64类型
questionId, err := strconv.ParseInt(questionId, 10, 64)
if err != nil {
tx.Rollback()
return false, errors.New("删除失败")
}
_, err = questionDao.GetQuestionById(questionId)
if err != nil {
tx.Rollback()
return false, errors.New("题目不存在")
}
// 删除选项
err = questionOptionDao.DeleteQuestionOptionByQuestionId(tx, questionId)
if err != nil {
tx.Rollback()
return false, errors.New(err.Error())
}
err = questionDao.DeleteQuestionById(tx, questionId)
if err != nil {
tx.Rollback()
return false, errors.New("删除失败")
}
}
tx.Commit()
return true, nil
}
// GetQuestion 获取题目详情
func (r *QuestionService) GetQuestion(questionId int64) (g *dto.QuestionDto, err error) {
questionDao := dao.QuestionDao{}
question, err := questionDao.GetQuestionPreloadById(questionId)
if err != nil {
return nil, errors.New("题目不存在")
}
if question.QuestionStatus == 2 {
return nil, errors.New("题目已禁用")
}
if question.IsDelete == 1 {
return nil, errors.New("题目已删除")
}
// 处理返回值
g = dto.GetQuestionDto(question)
// 加载一级标签
if question.FirstLabelId != nil {
labelDao := dao.LabelDao{}
firstLabel, err := labelDao.GetLabelFirstById(*question.FirstLabelId)
if err != nil {
return nil, errors.New("题目标签存在错误")
}
g.LoadFirstLabel(firstLabel)
}
// 加载二级标签
if question.SecondLabelId != nil {
labelDao := dao.LabelDao{}
secondLabel, err := labelDao.GetLabelFirstById(*question.SecondLabelId)
if err != nil {
return nil, errors.New("题目标签存在错误")
}
g.LoadSecondLabel(secondLabel)
}
// 加载选项
g.LoadQuestionOption(question.QuestionOption)
// 加载图片
g.LoadQuestionImage(question.QuestionImage)
// 加载答案
g.LoadQuestionAnswer(question)
return g, nil
}