重构试卷相关内容
This commit is contained in:
@@ -352,63 +352,79 @@ namespace TechHelper.Server.Services
|
||||
Guid? parentAssignmentGroupId,
|
||||
Guid createdById)
|
||||
{
|
||||
byte groupNumber = 1;
|
||||
var newAssignmentGroup = new AssignmentGroup
|
||||
if (qgDto.ValidQuestionGroup)
|
||||
{
|
||||
Id = Guid.NewGuid(), // 后端生成 GUID
|
||||
Title = qgDto.Title,
|
||||
Descript = qgDto.Descript,
|
||||
TotalPoints = qgDto.Score,
|
||||
Number = (byte)qgDto.Index,
|
||||
ValidQuestionGroup = qgDto.ValidQuestionGroup,
|
||||
ParentGroup = parentAssignmentGroupId,
|
||||
AssignmentId = parentAssignmentGroupId == null ? assignmentId : (Guid?)null,
|
||||
IsDeleted = false
|
||||
};
|
||||
await _unitOfWork.GetRepository<AssignmentGroup>().InsertAsync(newAssignmentGroup);
|
||||
|
||||
// 处理子题目
|
||||
uint questionNumber = 1;
|
||||
foreach (var sqDto in qgDto.SubQuestions.OrderBy(s => s.Index))
|
||||
await SaveQuestionGroup(qgDto);
|
||||
}
|
||||
else
|
||||
{
|
||||
var newQuestion = _mapper.Map<Question>(sqDto);
|
||||
newQuestion.Id = Guid.NewGuid();
|
||||
newQuestion.CreatedBy = createdById;
|
||||
newQuestion.CreatedAt = DateTime.UtcNow;
|
||||
newQuestion.UpdatedAt = DateTime.UtcNow;
|
||||
newQuestion.IsDeleted = false;
|
||||
newQuestion.SubjectArea = EnumMappingHelpers.ParseEnumSafe(subjectarea, SubjectAreaEnum.Unknown);
|
||||
byte groupNumber = 1;
|
||||
|
||||
await _unitOfWork.GetRepository<Question>().InsertAsync(newQuestion);
|
||||
|
||||
var newAssignmentQuestion = new AssignmentQuestion
|
||||
var newAssignmentGroup = new AssignmentGroup
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
QuestionId = newQuestion.Id,
|
||||
QuestionNumber = (byte)questionNumber,
|
||||
AssignmentGroupId = newAssignmentGroup.Id,
|
||||
Score = sqDto.Score,
|
||||
IsDeleted = false,
|
||||
CreatedAt = DateTime.UtcNow
|
||||
Id = Guid.NewGuid(), // 后端生成 GUID
|
||||
Title = qgDto.Title,
|
||||
Descript = qgDto.Descript,
|
||||
TotalPoints = qgDto.Score,
|
||||
Number = (byte)qgDto.Index,
|
||||
ValidQuestionGroup = qgDto.ValidQuestionGroup,
|
||||
ParentGroup = parentAssignmentGroupId,
|
||||
AssignmentId = parentAssignmentGroupId == null ? assignmentId : (Guid?)null,
|
||||
IsDeleted = false
|
||||
};
|
||||
await _unitOfWork.GetRepository<AssignmentQuestion>().InsertAsync(newAssignmentQuestion);
|
||||
await _unitOfWork.GetRepository<AssignmentGroup>().InsertAsync(newAssignmentGroup);
|
||||
|
||||
questionNumber++;
|
||||
}
|
||||
// 处理子题目
|
||||
uint questionNumber = 1;
|
||||
foreach (var sqDto in qgDto.SubQuestions.OrderBy(s => s.Index))
|
||||
{
|
||||
var newQuestion = _mapper.Map<Question>(sqDto);
|
||||
newQuestion.Id = Guid.NewGuid();
|
||||
newQuestion.CreatedBy = createdById;
|
||||
newQuestion.CreatedAt = DateTime.UtcNow;
|
||||
newQuestion.UpdatedAt = DateTime.UtcNow;
|
||||
newQuestion.IsDeleted = false;
|
||||
newQuestion.SubjectArea = EnumMappingHelpers.ParseEnumSafe(subjectarea, SubjectAreaEnum.Unknown);
|
||||
|
||||
// 递归处理子题组
|
||||
// 这里需要遍历 SubQuestionGroups,并对每个子组进行递归调用
|
||||
foreach (var subQgDto in qgDto.SubQuestionGroups.OrderBy(s => s.Index))
|
||||
{
|
||||
await ProcessAndSaveAssignmentGroupsRecursive(
|
||||
subQgDto, // 传入当前的子题组 DTO
|
||||
subjectarea,
|
||||
assignmentId, // 顶层 AssignmentId 依然传递下去,但子组不会直接使用它
|
||||
newAssignmentGroup.Id, // 将当前题组的 ID 作为下一层递归的 parentAssignmentGroupId
|
||||
createdById);
|
||||
await _unitOfWork.GetRepository<Question>().InsertAsync(newQuestion);
|
||||
|
||||
var newAssignmentQuestion = new AssignmentQuestion
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
QuestionId = newQuestion.Id,
|
||||
QuestionNumber = (byte)questionNumber,
|
||||
AssignmentGroupId = newAssignmentGroup.Id,
|
||||
Score = sqDto.Score,
|
||||
IsDeleted = false,
|
||||
CreatedAt = DateTime.UtcNow
|
||||
};
|
||||
await _unitOfWork.GetRepository<AssignmentQuestion>().InsertAsync(newAssignmentQuestion);
|
||||
|
||||
questionNumber++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 递归处理子题组
|
||||
// 这里需要遍历 SubQuestionGroups,并对每个子组进行递归调用
|
||||
foreach (var subQgDto in qgDto.SubQuestionGroups.OrderBy(s => s.Index))
|
||||
{
|
||||
await ProcessAndSaveAssignmentGroupsRecursive(
|
||||
subQgDto, // 传入当前的子题组 DTO
|
||||
subjectarea,
|
||||
assignmentId, // 顶层 AssignmentId 依然传递下去,但子组不会直接使用它
|
||||
newAssignmentGroup.Id, // 将当前题组的 ID 作为下一层递归的 parentAssignmentGroupId
|
||||
createdById);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveQuestionGroup(QuestionGroupDto qgDto)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public async Task<ApiResponse> GetAllExamPreview(Guid user)
|
||||
{
|
||||
try
|
||||
@@ -419,7 +435,7 @@ namespace TechHelper.Server.Services
|
||||
if (assignments.Any())
|
||||
{
|
||||
var exam = _mapper.Map<IEnumerable<ExamDto>>(assignments);
|
||||
return ApiResponse.Success(result: exam);
|
||||
return ApiResponse.Success(result: exam);
|
||||
}
|
||||
|
||||
return ApiResponse.Error("你还没有创建任何试卷");
|
||||
|
115
TechHelper.Server/Services/ExamService2.cs
Normal file
115
TechHelper.Server/Services/ExamService2.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using AutoMapper;
|
||||
using Entities.Contracts;
|
||||
using Entities.DTO;
|
||||
using SharedDATA.Api;
|
||||
using TechHelper.Server.Repository;
|
||||
using TechHelper.Services;
|
||||
|
||||
namespace TechHelper.Server.Services
|
||||
{
|
||||
|
||||
public class ExamService2 : IExamService2
|
||||
{
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly IExamRepository _examRepository;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public ExamService2(IUnitOfWork unitOfWork, IExamRepository examRepository, IMapper mapper)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
_examRepository = examRepository;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
public async Task<Guid> CreateExamAsync(ExamDto examDto, Guid creatorId)
|
||||
{
|
||||
if (examDto.QuestionGroups == null)
|
||||
{
|
||||
throw new ArgumentException("试卷必须包含一个根题组。");
|
||||
}
|
||||
|
||||
// 使用 AutoMapper 将 DTO 映射到实体
|
||||
var assignment = _mapper.Map<Assignment>(examDto);
|
||||
|
||||
// 设置后端生成的属性
|
||||
assignment.Id = Guid.NewGuid();
|
||||
assignment.CreatedBy = creatorId;
|
||||
assignment.CreatedAt = DateTime.UtcNow;
|
||||
|
||||
// 递归设置所有子实体的ID和关联关系
|
||||
SetEntityIdsAndRelations(assignment.AssignmentGroups.First(), assignment.Id, creatorId);
|
||||
|
||||
await _examRepository.AddAsync(assignment);
|
||||
await _unitOfWork.SaveChangesAsync();
|
||||
|
||||
return assignment.Id;
|
||||
}
|
||||
|
||||
private void SetEntityIdsAndRelations(AssignmentGroup group, Guid? assignmentId, Guid creatorId)
|
||||
{
|
||||
group.Id = Guid.NewGuid();
|
||||
group.AssignmentId = assignmentId;
|
||||
|
||||
foreach (var aq in group.AssignmentQuestions)
|
||||
{
|
||||
aq.Id = Guid.NewGuid();
|
||||
aq.AssignmentGroupId = group.Id;
|
||||
aq.Question.Id = Guid.NewGuid();
|
||||
aq.Question.CreatedBy = creatorId;
|
||||
aq.CreatedAt = DateTime.UtcNow;
|
||||
// ... 其他默认值
|
||||
}
|
||||
|
||||
foreach (var childGroup in group.ChildAssignmentGroups)
|
||||
{
|
||||
// 子题组的 AssignmentId 为 null,通过 ParentGroup 关联
|
||||
SetEntityIdsAndRelations(childGroup, null, creatorId);
|
||||
childGroup.ParentGroup = group.Id;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ExamDto> GetExamByIdAsync(Guid id)
|
||||
{
|
||||
var assignment = await _examRepository.GetFullExamByIdAsync(id);
|
||||
if (assignment == null)
|
||||
{
|
||||
|
||||
throw new InvalidOperationException("");
|
||||
}
|
||||
|
||||
return _mapper.Map<ExamDto>(assignment);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<ExamDto>> GetAllExamPreviewsAsync(Guid userId)
|
||||
{
|
||||
var assignments = await _examRepository.GetExamPreviewsByUserAsync(userId);
|
||||
return _mapper.Map<IEnumerable<ExamDto>>(assignments);
|
||||
}
|
||||
|
||||
public Task<ApiResponse> GetAllAsync(QueryParameter query)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<ApiResponse> GetAsync(Guid id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<ApiResponse> AddAsync(ExamDto model)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<ApiResponse> UpdateAsync(ExamDto model)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<ApiResponse> DeleteAsync(Guid id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
9
TechHelper.Server/Services/IAssignmentGroupService.cs
Normal file
9
TechHelper.Server/Services/IAssignmentGroupService.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using Entities.Contracts;
|
||||
using TechHelper.Services;
|
||||
|
||||
namespace TechHelper.Server.Services
|
||||
{
|
||||
public interface IAssignmentGroupService : IBaseService<AssignmentGroup, Guid>
|
||||
{
|
||||
}
|
||||
}
|
@@ -1,4 +1,5 @@
|
||||
using Entities.DTO;
|
||||
using Entities.Contracts;
|
||||
using Entities.DTO;
|
||||
using TechHelper.Services;
|
||||
|
||||
namespace TechHelper.Server.Services
|
||||
@@ -6,5 +7,6 @@ namespace TechHelper.Server.Services
|
||||
public interface IExamService : IBaseService<ExamDto, Guid>
|
||||
{
|
||||
Task<ApiResponse> GetAllExamPreview(Guid user);
|
||||
QuestionGroupDto MapAssignmentGroupToDto(AssignmentGroup ag);
|
||||
}
|
||||
}
|
||||
|
26
TechHelper.Server/Services/IExamService2.cs
Normal file
26
TechHelper.Server/Services/IExamService2.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Entities.Contracts;
|
||||
using Entities.DTO;
|
||||
using TechHelper.Services;
|
||||
|
||||
namespace TechHelper.Server.Services
|
||||
{
|
||||
public interface IExamService2 : IBaseService<ExamDto, Guid>
|
||||
{
|
||||
/// <summary>
|
||||
/// 根据 ID 获取试卷 DTO。
|
||||
/// </summary>
|
||||
Task<ExamDto> GetExamByIdAsync(Guid id);
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定用户的所有试卷预览。
|
||||
/// </summary>
|
||||
Task<IEnumerable<ExamDto>> GetAllExamPreviewsAsync(Guid userId);
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个新的试卷。
|
||||
/// </summary>
|
||||
/// <returns>创建成功的试卷ID</returns>
|
||||
Task<Guid> CreateExamAsync(ExamDto examDto, Guid creatorId);
|
||||
|
||||
}
|
||||
}
|
9
TechHelper.Server/Services/IQuestionGroupService.cs
Normal file
9
TechHelper.Server/Services/IQuestionGroupService.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using Entities.Contracts;
|
||||
using TechHelper.Services;
|
||||
|
||||
namespace TechHelper.Server.Services
|
||||
{
|
||||
public interface IQuestionGroupService : IBaseService<QuestionGroup, Guid>
|
||||
{
|
||||
}
|
||||
}
|
11
TechHelper.Server/Services/IQuestionService.cs
Normal file
11
TechHelper.Server/Services/IQuestionService.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Entities.Contracts;
|
||||
using TechHelper.Services;
|
||||
|
||||
namespace TechHelper.Server.Services
|
||||
{
|
||||
public interface IQuestionService : IBaseService<Question, Guid>
|
||||
{
|
||||
Task<ApiResponse> FindByTitle(string title);
|
||||
Task<ApiResponse> CheckTitlesExistence(IEnumerable<string> titles);
|
||||
}
|
||||
}
|
66
TechHelper.Server/Services/QuestionGroupService.cs
Normal file
66
TechHelper.Server/Services/QuestionGroupService.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using AutoMapper;
|
||||
using Entities.Contracts;
|
||||
using Entities.DTO;
|
||||
using SharedDATA.Api;
|
||||
using TechHelper.Services;
|
||||
|
||||
namespace TechHelper.Server.Services
|
||||
{
|
||||
public class QuestionGroupService : IAssignmentGroupService
|
||||
{
|
||||
|
||||
private readonly IUnitOfWork _work;
|
||||
// 如果不再需要 AutoMapper 进行实体到 DTO 的映射,可以移除 _mapper 字段
|
||||
// 但如果 AutoMapper 在其他服务中用于其他映射,或者将来可能需要,可以保留
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IExamService _examService;
|
||||
|
||||
public QuestionGroupService(IUnitOfWork work, IMapper mapper, IExamService examService)
|
||||
{
|
||||
_work = work;
|
||||
_mapper = mapper;
|
||||
_examService = examService;
|
||||
}
|
||||
|
||||
|
||||
public Task<ApiResponse> AddAsync(AssignmentGroup model)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<ApiResponse> DeleteAsync(Guid id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<ApiResponse> GetAllAsync(QueryParameter query)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task<ApiResponse> GetAsync(Guid id)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
var result = await _work.GetRepository<AssignmentGroup>().GetFirstOrDefaultAsync(predicate: ag => ag.Id == id);
|
||||
QuestionGroupDto qgd = new QuestionGroupDto();
|
||||
if (result != null)
|
||||
{
|
||||
qgd = _examService.MapAssignmentGroupToDto(result);
|
||||
return ApiResponse.Success(result: qgd);
|
||||
}
|
||||
return ApiResponse.Error("没找到问题组");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ApiResponse.Error($"出现了一点问题: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public Task<ApiResponse> UpdateAsync(AssignmentGroup model)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
261
TechHelper.Server/Services/QuestionService.cs
Normal file
261
TechHelper.Server/Services/QuestionService.cs
Normal file
@@ -0,0 +1,261 @@
|
||||
using AutoMapper;
|
||||
using Entities.Contracts;
|
||||
using SharedDATA.Api;
|
||||
using TechHelper.Services;
|
||||
using System.Linq.Expressions;
|
||||
using System.Linq;
|
||||
using Entities; // 引入你的 Question 实体所在的命名空间
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Entities.DTO; // 引入 EF Core 用于 Include (如果需要)
|
||||
|
||||
namespace TechHelper.Server.Services
|
||||
{
|
||||
public class QuestionService : IQuestionService
|
||||
{
|
||||
private readonly IUnitOfWork _work;
|
||||
// 如果不再需要 AutoMapper 进行实体到 DTO 的映射,可以移除 _mapper 字段
|
||||
// 但如果 AutoMapper 在其他服务中用于其他映射,或者将来可能需要,可以保留
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IExamService _examService;
|
||||
|
||||
public QuestionService(IUnitOfWork work, IMapper mapper, IExamService examService)
|
||||
{
|
||||
_work = work;
|
||||
_mapper = mapper;
|
||||
_examService = examService;
|
||||
}
|
||||
|
||||
public async Task<ApiResponse> AddAsync(Question model)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 可以在此处进行业务逻辑校验,例如检查题目是否已存在
|
||||
var existingQuestion = await _work.GetRepository<Question>().GetFirstOrDefaultAsync(
|
||||
predicate: q => q.QuestionText == model.QuestionText && !q.IsDeleted
|
||||
);
|
||||
|
||||
if (existingQuestion != null)
|
||||
{
|
||||
return ApiResponse.Error($"题目 '{model.QuestionText}' 已存在,请勿重复添加。");
|
||||
}
|
||||
|
||||
// 设置创建时间、创建者等通用属性
|
||||
model.Id = Guid.NewGuid();
|
||||
model.CreatedAt = DateTime.UtcNow;
|
||||
model.UpdatedAt = DateTime.UtcNow;
|
||||
model.IsDeleted = false;
|
||||
model.ValidQuestion = true; // 假设新添加的题目默认为有效
|
||||
// model.CreatedBy = ... // 实际应用中,这里应该从当前用户上下文获取
|
||||
|
||||
await _work.GetRepository<Question>().InsertAsync(model);
|
||||
await _work.SaveChangesAsync();
|
||||
|
||||
// 直接返回 Question 实体
|
||||
return ApiResponse.Success("题目添加成功。", model);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ApiResponse.Error($"添加题目失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ApiResponse> DeleteAsync(Guid id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var questionToDelete = await _work.GetRepository<Question>().GetFirstOrDefaultAsync(predicate: q => q.Id == id && !q.IsDeleted);
|
||||
|
||||
if (questionToDelete == null)
|
||||
{
|
||||
return ApiResponse.Error($"找不到 ID 为 {id} 的题目,或者该题目已被删除。");
|
||||
}
|
||||
|
||||
// 软删除
|
||||
questionToDelete.IsDeleted = true;
|
||||
questionToDelete.UpdatedAt = DateTime.UtcNow;
|
||||
_work.GetRepository<Question>().Update(questionToDelete);
|
||||
|
||||
await _work.SaveChangesAsync();
|
||||
|
||||
return ApiResponse.Success($"ID 为 {id} 的题目已成功删除 (软删除)。");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ApiResponse.Error($"删除题目时发生错误: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ApiResponse> FindByTitle(string title)
|
||||
{
|
||||
try
|
||||
{
|
||||
var question = await _work.GetRepository<Question>().GetFirstOrDefaultAsync(
|
||||
predicate: q => q.QuestionText == title && !q.IsDeleted
|
||||
);
|
||||
|
||||
if (question == null)
|
||||
{
|
||||
return ApiResponse.Error($"未找到题目 '{title}'。");
|
||||
}
|
||||
|
||||
// 直接返回 Question 实体
|
||||
return ApiResponse.Success(result: question);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ApiResponse.Error($"查找题目时出现问题: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ApiResponse> CheckTitlesExistence(IEnumerable<string> titles)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (titles == null || !titles.Any())
|
||||
{
|
||||
return ApiResponse.Success("未指定查询的题目文本,返回空结果。", new Dictionary<string, bool>());
|
||||
}
|
||||
|
||||
var distinctTitles = titles.Distinct(StringComparer.OrdinalIgnoreCase).ToList();
|
||||
|
||||
var existingQuestions = await _work.GetRepository<Question>().GetAllAsync(
|
||||
predicate: q => distinctTitles.Contains(q.QuestionText) && !q.IsDeleted
|
||||
);
|
||||
|
||||
var existingQuestionTexts = new HashSet<string>(existingQuestions.Select(q => q.QuestionText), StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
var resultDictionary = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var title in titles)
|
||||
{
|
||||
resultDictionary[title] = existingQuestionTexts.Contains(title);
|
||||
}
|
||||
|
||||
return ApiResponse.Success(result: resultDictionary);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ApiResponse.Error($"批量查找题目存在性时出现问题: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ApiResponse> GetAllAsync(QueryParameter query)
|
||||
{
|
||||
try
|
||||
{
|
||||
Expression<Func<Question, bool>> predicate = q => !q.IsDeleted;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(query.Search))
|
||||
{
|
||||
predicate = predicate.And(q => q.QuestionText.Contains(query.Search));
|
||||
}
|
||||
|
||||
Func<IQueryable<Question>, IOrderedQueryable<Question>> orderBy = null;
|
||||
if (true)
|
||||
{
|
||||
|
||||
orderBy = q => q.OrderByDescending(x => x.CreatedAt);
|
||||
}
|
||||
else
|
||||
{
|
||||
orderBy = q => q.OrderByDescending(x => x.CreatedAt);
|
||||
}
|
||||
|
||||
var questions = await _work.GetRepository<Question>().GetPagedListAsync(
|
||||
predicate: predicate,
|
||||
orderBy: orderBy,
|
||||
pageIndex: query.PageIndex,
|
||||
pageSize: query.PageSize
|
||||
);
|
||||
|
||||
if (!questions.Items.Any())
|
||||
{
|
||||
return ApiResponse.Error("未找到任何题目。", Enumerable.Empty<Question>()); // 返回空 Question 集合
|
||||
}
|
||||
|
||||
// 直接返回 Question 实体集合
|
||||
return ApiResponse.Success(result: questions);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ApiResponse.Error($"获取题目列表时出现问题: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ApiResponse> GetAsync(Guid id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var question = await _work.GetRepository<Question>().GetFirstOrDefaultAsync(predicate: q => q.Id == id && !q.IsDeleted);
|
||||
|
||||
if (question == null)
|
||||
{
|
||||
return ApiResponse.Error($"找不到 ID 为 {id} 的题目。");
|
||||
}
|
||||
|
||||
// 直接返回 Question 实体
|
||||
return ApiResponse.Success(result: question);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ApiResponse.Error($"获取题目时发生错误: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ApiResponse> UpdateAsync(Question model)
|
||||
{
|
||||
try
|
||||
{
|
||||
var existingQuestion = await _work.GetRepository<Question>().GetFirstOrDefaultAsync(predicate: q => q.Id == model.Id && !q.IsDeleted);
|
||||
|
||||
if (existingQuestion == null)
|
||||
{
|
||||
return ApiResponse.Error($"找不到 ID 为 {model.Id} 的题目,无法更新。");
|
||||
}
|
||||
|
||||
// 检查更新后的题目文本是否与现有其他题目重复
|
||||
var duplicateCheck = await _work.GetRepository<Question>().GetFirstOrDefaultAsync(
|
||||
predicate: q => q.Id != model.Id && q.QuestionText == model.QuestionText && !q.IsDeleted
|
||||
);
|
||||
|
||||
if (duplicateCheck != null)
|
||||
{
|
||||
return ApiResponse.Error($"题目文本 '{model.QuestionText}' 已被其他题目占用,请修改。");
|
||||
}
|
||||
|
||||
// 手动复制属性或使用 AutoMapper (如果保留了 _mapper 字段)
|
||||
// 如果选择手动复制,请确保复制所有需要更新的属性
|
||||
existingQuestion = model;
|
||||
|
||||
_work.GetRepository<Question>().Update(existingQuestion);
|
||||
await _work.SaveChangesAsync();
|
||||
|
||||
// 直接返回更新后的 Question 实体
|
||||
return ApiResponse.Success("题目更新成功。", existingQuestion);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ApiResponse.Error($"更新题目失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// PredicateBuilder 保持不变,如果你没有使用 LinqKit,这部分是必需的
|
||||
public static class PredicateBuilder
|
||||
{
|
||||
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
|
||||
{
|
||||
var invokedExpr = Expression.Invoke(second, first.Parameters.Cast<Expression>());
|
||||
return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(first.Body, invokedExpr), first.Parameters);
|
||||
}
|
||||
|
||||
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
|
||||
{
|
||||
var invokedExpr = Expression.Invoke(second, first.Parameters.Cast<Expression>());
|
||||
return Expression.Lambda<Func<T, bool>>(Expression.OrElse(first.Body, invokedExpr), first.Parameters);
|
||||
}
|
||||
|
||||
public static Expression<Func<T, bool>> True<T>() { return f => true; }
|
||||
public static Expression<Func<T, bool>> False<T>() { return f => false; }
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user