229 lines
6.3 KiB
Go
229 lines
6.3 KiB
Go
package service
|
||
|
||
import (
|
||
"fmt"
|
||
|
||
"dd_fiber_api/internal/question"
|
||
"dd_fiber_api/internal/question/dao"
|
||
)
|
||
|
||
// PaperService 试卷服务
|
||
type PaperService struct {
|
||
paperDAO dao.PaperDAOInterface
|
||
materialService *MaterialService
|
||
}
|
||
|
||
// NewPaperService 创建试卷服务
|
||
func NewPaperService(paperDAO dao.PaperDAOInterface, materialService *MaterialService) *PaperService {
|
||
return &PaperService{
|
||
paperDAO: paperDAO,
|
||
materialService: materialService,
|
||
}
|
||
}
|
||
|
||
// CreatePaper 创建试卷
|
||
func (s *PaperService) CreatePaper(req *CreatePaperRequest) (*question.Paper, error) {
|
||
// 验证:题目数量不能为空
|
||
if req.QuestionIds == nil || len(req.QuestionIds) == 0 {
|
||
return nil, fmt.Errorf("题目数量不能为空,请至少选择一个题目")
|
||
}
|
||
|
||
paperID := question.GenerateID()
|
||
|
||
// 确保 MaterialIds 不为 nil
|
||
materialIds := req.MaterialIds
|
||
if materialIds == nil {
|
||
materialIds = []string{}
|
||
}
|
||
|
||
// 确保 QuestionIDs 不为 nil(已验证不为空,但确保不为 nil)
|
||
questionIds := req.QuestionIds
|
||
if questionIds == nil {
|
||
questionIds = []string{}
|
||
}
|
||
|
||
paper := &question.Paper{
|
||
ID: paperID,
|
||
Title: req.Title,
|
||
Description: req.Description,
|
||
Source: req.Source,
|
||
QuestionIDs: questionIds,
|
||
MaterialIDs: materialIds,
|
||
CreatedAt: question.GetCurrentTimestamp(),
|
||
UpdatedAt: question.GetCurrentTimestamp(),
|
||
}
|
||
|
||
err := s.paperDAO.Create(paper)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("创建试卷失败: %v", err)
|
||
}
|
||
|
||
return paper, nil
|
||
}
|
||
|
||
// GetPaper 获取试卷
|
||
func (s *PaperService) GetPaper(id string) (*question.Paper, error) {
|
||
paper, err := s.paperDAO.GetWithQuestions(id)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("试卷不存在: %v", err)
|
||
}
|
||
|
||
// 收集材料 ID:试卷级 + 题目级(按题目中首次出现顺序去重),并拉取材料详情
|
||
if s.materialService != nil {
|
||
seen := make(map[string]bool)
|
||
var orderedIDs []string
|
||
for _, mid := range paper.MaterialIDs {
|
||
if mid != "" && !seen[mid] {
|
||
seen[mid] = true
|
||
orderedIDs = append(orderedIDs, mid)
|
||
}
|
||
}
|
||
if paper.Questions != nil {
|
||
for _, q := range paper.Questions {
|
||
if q.MaterialID != "" && !seen[q.MaterialID] {
|
||
seen[q.MaterialID] = true
|
||
orderedIDs = append(orderedIDs, q.MaterialID)
|
||
}
|
||
}
|
||
}
|
||
for _, mid := range orderedIDs {
|
||
mat, err := s.materialService.GetMaterial(mid)
|
||
if err != nil {
|
||
continue
|
||
}
|
||
paper.Materials = append(paper.Materials, mat)
|
||
}
|
||
}
|
||
|
||
return paper, nil
|
||
}
|
||
|
||
// SearchPapers 搜索试卷
|
||
func (s *PaperService) SearchPapers(query string, page, pageSize int32) ([]*question.Paper, int32, error) {
|
||
papers, total, err := s.paperDAO.Search(query, page, pageSize)
|
||
if err != nil {
|
||
return nil, 0, fmt.Errorf("搜索试卷失败: %v", err)
|
||
}
|
||
|
||
return papers, total, nil
|
||
}
|
||
|
||
// UpdatePaper 更新试卷
|
||
func (s *PaperService) UpdatePaper(req *UpdatePaperRequest) error {
|
||
// 验证:题目数量不能为空
|
||
if req.QuestionIds == nil || len(req.QuestionIds) == 0 {
|
||
return fmt.Errorf("题目数量不能为空,请至少选择一个题目")
|
||
}
|
||
|
||
paper, err := s.paperDAO.GetByID(req.Id)
|
||
if err != nil {
|
||
return fmt.Errorf("试卷不存在: %v", err)
|
||
}
|
||
|
||
paper.Title = req.Title
|
||
paper.Description = req.Description
|
||
paper.Source = req.Source
|
||
// 确保 QuestionIDs 不为 nil(已验证不为空,但确保不为 nil)
|
||
questionIds := req.QuestionIds
|
||
if questionIds == nil {
|
||
questionIds = []string{}
|
||
}
|
||
paper.QuestionIDs = questionIds
|
||
// 确保 MaterialIds 不为 nil
|
||
materialIds := req.MaterialIds
|
||
if materialIds == nil {
|
||
materialIds = []string{}
|
||
}
|
||
paper.MaterialIDs = materialIds
|
||
paper.UpdatedAt = question.GetCurrentTimestamp()
|
||
|
||
err = s.paperDAO.Update(paper)
|
||
if err != nil {
|
||
return fmt.Errorf("更新试卷失败: %v", err)
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// DeletePaper 删除试卷
|
||
func (s *PaperService) DeletePaper(id string) error {
|
||
err := s.paperDAO.Delete(id)
|
||
if err != nil {
|
||
return fmt.Errorf("删除试卷失败: %v", err)
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// BatchDeletePapers 批量删除试卷
|
||
func (s *PaperService) BatchDeletePapers(ids []string) (int, []string, error) {
|
||
deletedCount, failedIDs, err := s.paperDAO.BatchDelete(ids)
|
||
if err != nil {
|
||
return 0, nil, fmt.Errorf("批量删除失败: %v", err)
|
||
}
|
||
|
||
return deletedCount, failedIDs, nil
|
||
}
|
||
|
||
// AddQuestionToPaper 添加题目到试卷
|
||
func (s *PaperService) AddQuestionToPaper(paperID string, questionIDs []string) (int, []string, error) {
|
||
addedCount, failedIDs, err := s.paperDAO.AddQuestions(paperID, questionIDs)
|
||
if err != nil {
|
||
return 0, nil, fmt.Errorf("添加题目失败: %v", err)
|
||
}
|
||
|
||
return addedCount, failedIDs, nil
|
||
}
|
||
|
||
// RemoveQuestionFromPaper 从试卷移除题目
|
||
func (s *PaperService) RemoveQuestionFromPaper(paperID string, questionIDs []string) (int, []string, error) {
|
||
removedCount, failedIDs, err := s.paperDAO.RemoveQuestions(paperID, questionIDs)
|
||
if err != nil {
|
||
return 0, nil, fmt.Errorf("移除题目失败: %v", err)
|
||
}
|
||
|
||
return removedCount, failedIDs, nil
|
||
}
|
||
|
||
// GetPaperWithAnswers 获取试卷及题目详情(包含答案和解析,用于答题结果页面)
|
||
// 这个方法确保返回的题目包含答案和解析字段
|
||
func (s *PaperService) GetPaperWithAnswers(id string) (*question.Paper, error) {
|
||
paper, err := s.GetPaper(id)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 确保每个题目都有答案和解析字段(即使为空字符串)
|
||
if paper.Questions != nil {
|
||
for _, q := range paper.Questions {
|
||
if q.Answer == "" {
|
||
q.Answer = ""
|
||
}
|
||
if q.Explanation == "" {
|
||
q.Explanation = ""
|
||
}
|
||
}
|
||
}
|
||
|
||
return paper, nil
|
||
}
|
||
|
||
// CreatePaperRequest 创建试卷请求
|
||
type CreatePaperRequest struct {
|
||
Title string `json:"title"`
|
||
Description string `json:"description"`
|
||
Source string `json:"source,omitempty"` // 题目出处(可选)
|
||
QuestionIds []string `json:"question_ids"` // 题目ID列表
|
||
MaterialIds []string `json:"material_ids,omitempty"` // 关联的材料ID列表(可选,用于主观题组卷)
|
||
}
|
||
|
||
// UpdatePaperRequest 更新试卷请求
|
||
type UpdatePaperRequest struct {
|
||
Id string `json:"id"`
|
||
Title string `json:"title"`
|
||
Description string `json:"description"`
|
||
Source string `json:"source,omitempty"` // 题目出处(可选)
|
||
QuestionIds []string `json:"question_ids"` // 题目ID列表
|
||
MaterialIds []string `json:"material_ids,omitempty"` // 关联的材料ID列表(可选,用于主观题组卷)
|
||
}
|