using Mapster; using QYZH.InteractiveMagazine.Common.Extensions; using QYZH.InteractiveMagazine.Infrastructure.OSS; using QYZH.InteractiveMagazine.IService; using QYZH.InteractiveMagazine.Models.Common; using QYZH.InteractiveMagazine.Models.Dto; using QYZH.InteractiveMagazine.Models.Dto.Journal; using QYZH.InteractiveMagazine.Models.Entity; using QYZH.InteractiveMagazine.Models.Enum; using QYZH.InteractiveMagazine.Repository; using SqlSugar; using Yitter.IdGenerator; namespace QYZH.InteractiveMagazine.Service; public class JournalPageTaskService(BaseRepository journalRepository, OssService ossService, BaseRepository answerRepository) : BaseRepository, IJournalPageTaskService { public async Task InsertAsync(JournalPageTaskAddInput input) { var JournalStatus = await journalRepository.Queryable().Where(w => w.Id == input.JournalId).Select(s => s.Status).FirstAsync(); BusinessException.ThrowIf(JournalStatus == (int)JournalStatusEnum.Archive, "书籍已归档不能添加题目", ResultCode.CONFLICT); var map = input.Adapt(); map.Id = YitIdHelper.NextId(); map.GroupId = map.Id; map.NeedAiProcess = input.NeedAiProcess; var no = input.No.Split('-').Select(int.Parse).ToArray(); if (no.Last() >= 2) { var startNo = $"{no[0]}-{no[1]}-{no[2]}-1"; var groupTask = await Queryable().Where(w => w.No == startNo && w.JournalId == input.JournalId).FirstAsync(); BusinessException.ThrowIf(groupTask.IsNull(), "未找到关联跨页的第一部分", ResultCode.NOT_FOUND); map.GroupId = groupTask.GroupId; map.Type = groupTask.Type; } await base.InsertAsync(map); return map?.Id; } public async Task UpdateAsync(JournalPageTaskUpdateInput input) { var JournalStatus = await journalRepository.Queryable().Where(w => w.Id == input.JournalId).Select(s => s.Status).FirstAsync(); BusinessException.ThrowIf(JournalStatus == (int)JournalStatusEnum.Archive, "书籍已归档不能修改题目", ResultCode.CONFLICT); var task = await base.Queryable().Where(w => w.Id == input.Id).FirstAsync(); BusinessException.ThrowIf(task.IsNull(), "未找到关联的题号", ResultCode.NOT_FOUND); var sameTask = await base.Queryable().Where(w => w.No == input.No && w.JournalId == input.JournalId && w.Id != input.Id).FirstAsync(); BusinessException.ThrowIf(sameTask.IsNotEmpty(), "已经存在相同题号题目", ResultCode.CONFLICT); var key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.GroupId}"; // 题目内容处理 input.Task = Deal(task.Task, input.Task, key, "task"); task.Type = input.Type; task.Task = input.Task; task.Points = input.Points; task.GrowthPoint = (int?)input.GrowthPoint; task.Comprehension = input.Comprehension; task.Judgment = input.Judgment; task.Expression = input.Expression; task.Persuasiveness = input.Persuasiveness; task.AnswerTime = input.AnswerTime; task.Prompt = input.Prompt; task.NeedAiProcess = input.NeedAiProcess; var no = input.No.Split('-').Select(int.Parse).ToArray(); if (no.Last() >= 2) { var startNo = $"{no[0]}-{no[1]}-{no[2]}-1"; var groupTask = await Queryable().Where(w => w.No == startNo && w.JournalId == input.JournalId).FirstAsync(); BusinessException.ThrowIf(groupTask.IsNull(), "未找到关联跨页的第一部分", ResultCode.NOT_FOUND); task.GroupId = groupTask.GroupId; task.Type = groupTask.Type; } var taskResult = await base.Updateable(task).ExecuteCommandAsync() > 0; return taskResult; } public async Task DetailAsync(long id) { var task = await base.Queryable().Where(w => w.Id == id).FirstAsync(); if (task == null) return null; var data = new JournalPageTaskOutput { Id = task.Id, JournalId = task.JournalId, JournalPageId = task.JournalPageId, No = task.No, Type = task.Type, Points = task.Points, GrowthPoint = task.GrowthPoint ?? 0, Comprehension = task.Comprehension, Judgment = task.Judgment, Expression = task.Expression, Persuasiveness = task.Persuasiveness, AnswerTime = task.AnswerTime, Prompt = task.Prompt, NeedAiProcess = task.NeedAiProcess }; // 查询答案列表 var answers = await answerRepository.Queryable() .Where(a => a.JournalPageTaskId == id) .ToListAsync(); data.Answers = answers.Select(a => new JournalTaskAnswerOutput { Id = a.Id, Answer = a.Answer, AnswerUrl = a.AnswerUrL }).ToList(); return data; } public async Task DeleteAsync(long id) { var task = await base.Queryable().Where(w => w.Id == id).FirstAsync(); BusinessException.ThrowIf(task.IsNull(), "问题不存在", ResultCode.NOT_FOUND); var key = $"journal/{task.JournalId}/{task.JournalPageId}/{id}"; // 同时删除关联的答案记录 await answerRepository.DeleteAsync(a => a.JournalPageTaskId == id); ossService.DeleteObject(key); return await base.DeleteAsync(d => d.Id == id); } public async Task ComplementAsync(JournalPageTaskComplementInput input) { var task = await base.Queryable().Where(w => w.Id == input.Id).FirstAsync(); BusinessException.ThrowIf(task.IsNull(), "问题不存在", ResultCode.NOT_FOUND); if (input.AudioUrl.NotNull()) { var key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.Id}/audio.{input.AudioUrl.ToExtension()}"; ossService.CopyObject(input.AudioUrl, key); input.AudioUrl = key; } if (input.PointsUrl.NotNull()) { var key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.Id}/points.json"; ossService.CopyObject(input.PointsUrl, key); input.PointsUrl = key; } return await Updateable(input.Adapt()).Where(w => w.Id == input.Id).ExecuteCommandAsync() > 0; } public async Task AddAnswerAsync(JournalTaskAnswerAddInput input) { var task = await base.Queryable().Where(w => w.Id == input.JournalPageTaskId).FirstAsync(); BusinessException.ThrowIf(task.IsNull(), "问题不存在", ResultCode.NOT_FOUND); var key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.GroupId}"; input.Answer = Deal(null, input.Answer, key, "answer"); input.AnswerUrl = Deal(null, input.AnswerUrl, key, "answerUrl"); var entity = new JournalPageTaskAnswer { JournalPageTaskId = input.JournalPageTaskId, Answer = input.Answer, AnswerUrL = input.AnswerUrl, CreatedBy = "System", CreatedAt = DateTime.Now, IsDeleted = false }; await answerRepository.InsertAsync(entity); return entity.Id; } public async Task UpdateAnswerAsync(JournalTaskAnswerUpdateInput input) { var answer = await answerRepository.Queryable().Where(a => a.Id == input.Id).FirstAsync(); BusinessException.ThrowIf(answer.IsNull(), "答案不存在", ResultCode.NOT_FOUND); var task = await base.Queryable().Where(w => w.Id == answer.JournalPageTaskId).FirstAsync(); var key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.GroupId}"; input.Answer = Deal(answer.Answer, input.Answer, key, "answer"); input.AnswerUrl = Deal(answer.AnswerUrL, input.AnswerUrl, key, "answerUrl"); return await answerRepository.Updateable() .SetColumns(a => a.Answer == input.Answer) .SetColumns(a => a.AnswerUrL == input.AnswerUrl) .Where(a => a.Id == input.Id) .ExecuteCommandAsync() > 0; } public async Task DeleteAnswerAsync(long id) { var answer = await answerRepository.Queryable().Where(a => a.Id == id).FirstAsync(); BusinessException.ThrowIf(answer.IsNull(), "答案不存在", ResultCode.NOT_FOUND); var task = await base.Queryable().Where(w => w.Id == answer.JournalPageTaskId).FirstAsync(); var key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.GroupId}"; // 清理OSS文件 Deal(answer.Answer, "", key, "answer"); Deal(answer.AnswerUrL, "", key, "answerUrl"); return await answerRepository.DeleteAsync(a => a.Id == id); } private string Deal(string oldUrls, string newUrls, string key, string type) { // 如果 newUrls 为空,则直接返回 if (newUrls.IsNull()) return null; // 处理 oldUrls 为 null 的情况,将其视为空字符串 var oldTaskUrls = oldUrls.AllUrl().Distinct(); var taskUrls = newUrls.AllUrl().Distinct().Select(s => s.RemoveDomain()); // 删除不存在的(存在于旧集合但不在新集合中) var removedUrls = oldTaskUrls.Except(taskUrls).ToList(); ossService.DeleteObjects(removedUrls); // 添加新增的(存在于新集合但不在旧集合中) var addedUrls = taskUrls.Except(oldTaskUrls).ToList(); foreach (var item in addedUrls) { var value = $"{key}/{type}/{YitIdHelper.NextId()}.{item.ToExtension()}"; ossService.CopyObject(item, value); newUrls = newUrls.Replace(item, value); } return newUrls; } }