package cc.mrbird.febs.ai.service.impl; import cc.mrbird.febs.ai.entity.*; import cc.mrbird.febs.ai.mapper.AiMemberAnswerMapper; import cc.mrbird.febs.ai.req.memberAnswer.*; import cc.mrbird.febs.ai.res.memberAnswer.*; import cc.mrbird.febs.ai.res.product.ApiProductVo; import cc.mrbird.febs.ai.res.productQuestionItem.ApiMemberAnswerItemVo; import cc.mrbird.febs.ai.service.*; import cc.mrbird.febs.ai.utils.UUID; import cc.mrbird.febs.common.entity.FebsResponse; import cc.mrbird.febs.common.utils.LoginUserUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUnit; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * AI用户答题记录 Service实现类 * * @author yourname * @date 2025-07-29 */ @Slf4j @Service @RequiredArgsConstructor public class AiMemberAnswerServiceImpl extends ServiceImpl implements AiMemberAnswerService { private final AiMemberAnswerMapper aiMemberAnswerMapper; private final AiMemberAnswerItemService aiMemberAnswerItemService; private final AiProductService aiProductService; private final AiProductQuestionService aiProductQuestionService; private final AiProductQuestionItemService aiProductQuestionItemService; @Override public AiMemberAnswer getOneByQuery(LambdaQueryWrapper aiMemberAnswerLambdaQueryWrapper) { aiMemberAnswerLambdaQueryWrapper.last("limit 1"); return aiMemberAnswerMapper.selectOne(aiMemberAnswerLambdaQueryWrapper); } @Override public FebsResponse startAnswerV2(ApiMemberAnswerDto dto) { String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid(); ApiMemberAnswerVoV2 apiMemberAnswerVoV2 = new ApiMemberAnswerVoV2(); String productId = dto.getId(); AiProduct aiProduct = aiProductService.getById(productId); if(ObjectUtil.isNull(aiProduct)){ throw new RuntimeException("产品不存在"); } //验证产品分类下是否有题目 String productCategoryId = aiProduct.getProductCategoryId(); LambdaQueryWrapper questionLambdaQueryWrapper = Wrappers.lambdaQuery(AiProductQuestion.class); questionLambdaQueryWrapper.eq(AiProductQuestion::getProductCategoryId,productCategoryId); questionLambdaQueryWrapper.eq(AiProductQuestion::getState,1); questionLambdaQueryWrapper.last("limit 1"); List aiProductQuestions = aiProductQuestionService.getListByQuery(questionLambdaQueryWrapper); if(CollUtil.isEmpty(aiProductQuestions)){ // todo 没有题目采用AI生成题目 throw new RuntimeException("产品没有题目"); } //判断该产品是否有正在进行的练习 Date createdTime = new Date(); LambdaQueryWrapper aiMemberAnswerLambdaQueryWrapper = Wrappers.lambdaQuery(AiMemberAnswer.class); aiMemberAnswerLambdaQueryWrapper.eq(AiMemberAnswer::getMemberId,memberUuid); aiMemberAnswerLambdaQueryWrapper.eq(AiMemberAnswer::getProductId,aiProduct.getId()); aiMemberAnswerLambdaQueryWrapper.eq(AiMemberAnswer::getState,0); AiMemberAnswer aiMemberAnswer = this.getOneByQuery(aiMemberAnswerLambdaQueryWrapper); if(ObjectUtil.isNull(aiMemberAnswer)){ Integer questionCount = aiProduct.getQuestionCount(); aiMemberAnswer = new AiMemberAnswer(); aiMemberAnswer.setId(UUID.getSimpleUUIDString()); aiMemberAnswer.setCreatedTime(createdTime); aiMemberAnswer.setUpdatedTime(createdTime); aiMemberAnswer.setProductId(aiProduct.getId()); aiMemberAnswer.setMemberId(memberUuid); aiMemberAnswer.setState(0); aiMemberAnswer.setScore(0); aiMemberAnswer.setQuestionCnt(questionCount); aiMemberAnswer.setDoneCnt(0); aiMemberAnswer.setCorrectCnt(0); aiMemberAnswerMapper.insert(aiMemberAnswer); List aiMemberAnswerItems = new ArrayList<>(); for (int i = 1; i <= questionCount; i++){ //初始化答题记录 AiProductQuestion aiProductQuestion = aiProductQuestionService.createQuestion(aiProduct.getId()); AiMemberAnswerItem aiMemberAnswerItem = new AiMemberAnswerItem(); aiMemberAnswerItem.setId(UUID.getSimpleUUIDString()); aiMemberAnswerItem.setCreatedTime(createdTime); aiMemberAnswerItem.setAnswerId(aiMemberAnswer.getId()); aiMemberAnswerItem.setProductId(aiMemberAnswer.getProductId()); aiMemberAnswerItem.setMemberId(memberUuid); aiMemberAnswerItem.setProductQuestionId(aiProductQuestion.getId()); aiMemberAnswerItem.setTitle(aiProductQuestion.getTitle()); aiMemberAnswerItem.setDifficulty(aiProductQuestion.getDifficulty()); aiMemberAnswerItem.setMemberAnswerState(0); aiMemberAnswerItem.setSort( i ); aiMemberAnswerItems.add(aiMemberAnswerItem); } aiMemberAnswerItemService.saveBatch(aiMemberAnswerItems); apiMemberAnswerVoV2.setCurrent(1); }else{ if (aiMemberAnswer.getQuestionCnt() > aiMemberAnswer.getDoneCnt()){ apiMemberAnswerVoV2.setCurrent(aiMemberAnswer.getDoneCnt() + 1); }else{ apiMemberAnswerVoV2.setCurrent(aiMemberAnswer.getDoneCnt()); } } apiMemberAnswerVoV2.setMemberAnswerId(aiMemberAnswer.getId()); return new FebsResponse().success().data(apiMemberAnswerVoV2); } @Override public FebsResponse startAnswer(ApiMemberAnswerDto dto) { String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid(); String productId = dto.getId(); AiProduct aiProduct = aiProductService.getById(productId); if(ObjectUtil.isNull(aiProduct)){ throw new RuntimeException("产品不存在"); } //验证产品分类下是否有题目 String productCategoryId = aiProduct.getProductCategoryId(); LambdaQueryWrapper questionLambdaQueryWrapper = Wrappers.lambdaQuery(AiProductQuestion.class); questionLambdaQueryWrapper.eq(AiProductQuestion::getProductCategoryId,productCategoryId); questionLambdaQueryWrapper.eq(AiProductQuestion::getState,1); questionLambdaQueryWrapper.last("limit 1"); List aiProductQuestions = aiProductQuestionService.getListByQuery(questionLambdaQueryWrapper); if(CollUtil.isEmpty(aiProductQuestions)){ // todo 没有题目采用AI生成题目 throw new RuntimeException("产品没有题目"); } //判断该产品是否有正在进行的练习 Date createdTime = new Date(); LambdaQueryWrapper aiMemberAnswerLambdaQueryWrapper = Wrappers.lambdaQuery(AiMemberAnswer.class); aiMemberAnswerLambdaQueryWrapper.eq(AiMemberAnswer::getMemberId,memberUuid); aiMemberAnswerLambdaQueryWrapper.eq(AiMemberAnswer::getProductId,aiProduct.getId()); aiMemberAnswerLambdaQueryWrapper.eq(AiMemberAnswer::getState,0); AiMemberAnswer aiMemberAnswer = this.getOneByQuery(aiMemberAnswerLambdaQueryWrapper); if(ObjectUtil.isNull(aiMemberAnswer)){ aiMemberAnswer = new AiMemberAnswer(); aiMemberAnswer.setId(UUID.getSimpleUUIDString()); aiMemberAnswer.setCreatedTime(createdTime); aiMemberAnswer.setUpdatedTime(createdTime); aiMemberAnswer.setProductId(aiProduct.getId()); aiMemberAnswer.setMemberId(memberUuid); aiMemberAnswer.setState(0); aiMemberAnswer.setScore(0); aiMemberAnswer.setQuestionCnt(aiProduct.getQuestionCount()); aiMemberAnswer.setDoneCnt(0); aiMemberAnswer.setCorrectCnt(0); aiMemberAnswerMapper.insert(aiMemberAnswer); } boolean checkMemberAnswerDone = this.checkMemberAnswerDone(aiMemberAnswer); if(!checkMemberAnswerDone){ return new FebsResponse().fail().message("您已完成本次答题"); } ApiMemberAnswerVo apiMemberAnswerVo = new ApiMemberAnswerVo(); apiMemberAnswerVo.setMemberAnswerId(aiMemberAnswer.getId()); apiMemberAnswerVo.setName(aiProduct.getName()); apiMemberAnswerVo.setQuestionCnt(aiMemberAnswer.getQuestionCnt()); apiMemberAnswerVo.setDoneCnt(aiMemberAnswer.getDoneCnt()); apiMemberAnswerVo.setCorrectCnt(aiMemberAnswer.getCorrectCnt()); apiMemberAnswerVo.setProductId(aiMemberAnswer.getProductId()); AiProductQuestion aiProductQuestion = aiProductQuestionService.createQuestion(aiProduct.getId()); if(ObjectUtil.isNotNull(aiProductQuestion)){ apiMemberAnswerVo.setProductQuestionId(aiProductQuestion.getId()); apiMemberAnswerVo.setTitle(aiProductQuestion.getTitle()); apiMemberAnswerVo.setDifficulty(aiProductQuestion.getDifficulty()); //初始化答题记录 AiMemberAnswerItem aiMemberAnswerItem = new AiMemberAnswerItem(); aiMemberAnswerItem.setId(UUID.getSimpleUUIDString()); aiMemberAnswerItem.setCreatedTime(createdTime); aiMemberAnswerItem.setAnswerId(aiMemberAnswer.getId()); aiMemberAnswerItem.setProductId(aiMemberAnswer.getProductId()); aiMemberAnswerItem.setMemberId(memberUuid); aiMemberAnswerItem.setProductQuestionId(aiProductQuestion.getId()); aiMemberAnswerItem.setTitle(aiProductQuestion.getTitle()); aiMemberAnswerItem.setDifficulty(aiProductQuestion.getDifficulty()); aiMemberAnswerItem.setMemberAnswerState(0); aiMemberAnswerItemService.save(aiMemberAnswerItem); apiMemberAnswerVo.setMemberAnswerState(aiMemberAnswerItem.getMemberAnswerState()); apiMemberAnswerVo.setMemberAnswerItemId(aiMemberAnswerItem.getId()); List answerList = new ArrayList<>(); LambdaQueryWrapper productQuestionItemLambdaQueryWrapper = Wrappers.lambdaQuery(AiProductQuestionItem.class); productQuestionItemLambdaQueryWrapper.eq(AiProductQuestionItem::getProductQuestionId,aiProductQuestion.getId()); productQuestionItemLambdaQueryWrapper.orderByAsc(AiProductQuestionItem::getCreatedTime); List aiProductQuestionItems = aiProductQuestionItemService.getListByQuery(productQuestionItemLambdaQueryWrapper); if (CollUtil.isNotEmpty(aiProductQuestionItems)){ for (AiProductQuestionItem aiProductQuestionItem : aiProductQuestionItems){ ApiMemberAnswerItemVo apiMemberAnswerItemVo = new ApiMemberAnswerItemVo(); apiMemberAnswerItemVo.setId(aiProductQuestionItem.getId()); apiMemberAnswerItemVo.setAnswer(aiProductQuestionItem.getAnswer()); apiMemberAnswerItemVo.setAnswerAnalysis(aiProductQuestionItem.getAnswerAnalysis()); apiMemberAnswerItemVo.setCorrectAnswer(aiProductQuestionItem.getCorrectAnswer()); answerList.add(apiMemberAnswerItemVo); } } apiMemberAnswerVo.setAnswerList(answerList); } return new FebsResponse().success().data(apiMemberAnswerVo); } @Override public boolean checkMemberAnswerDone(AiMemberAnswer aiMemberAnswer) { Integer doneCnt = aiMemberAnswer.getDoneCnt(); Integer questionCnt = aiMemberAnswer.getQuestionCnt(); if (questionCnt > doneCnt){ return true; } return false; } @Override public FebsResponse answer(ApiQuestionAnswerDto dto) { String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid(); ApiQuestionItemInfoVo apiQuestionItemInfoVo = new ApiQuestionItemInfoVo(); String productQuestionItemId = dto.getId(); String productQuestionId = dto.getProductQuestionId(); String memberAnswerId = dto.getMemberAnswerId(); String memberAnswerItemId = dto.getMemberAnswerItemId(); AiMemberAnswer aiMemberAnswer = this.getById(memberAnswerId); if(ObjectUtil.isNull(aiMemberAnswer)){ throw new RuntimeException("答题记录不存在"); } Date createdTime = new Date(); AiMemberAnswerItem aiMemberAnswerItem = aiMemberAnswerItemService.getById(memberAnswerItemId); aiMemberAnswerItem.setUpdatedTime(createdTime); AiProductQuestion aiProductQuestion = aiProductQuestionService.getById(productQuestionId); LambdaQueryWrapper productQuestionItemLambdaQueryWrapper = Wrappers.lambdaQuery(AiProductQuestionItem.class); productQuestionItemLambdaQueryWrapper.eq(AiProductQuestionItem::getProductQuestionId,aiProductQuestion.getId()); productQuestionItemLambdaQueryWrapper.eq(AiProductQuestionItem::getCorrectAnswer,1); List listByQuery = aiProductQuestionItemService.getListByQuery(productQuestionItemLambdaQueryWrapper); if(CollUtil.isNotEmpty(listByQuery)){ AiProductQuestionItem aiProductQuestionItem = listByQuery.get(0); aiMemberAnswerItem.setAnswer(aiProductQuestionItem.getId()); aiMemberAnswerItem.setCorrectAnswer(aiProductQuestionItem.getCorrectAnswer()); aiMemberAnswerItem.setAnswerAnalysis(aiProductQuestionItem.getAnswerAnalysis()); apiQuestionItemInfoVo.setAnswerID(aiProductQuestionItem.getId()); apiQuestionItemInfoVo.setAnswer(aiProductQuestionItem.getAnswer()); } aiMemberAnswerItem.setMemberAnswerQuestionId(productQuestionItemId); aiMemberAnswerItem.setMemberAnswerState( ObjectUtil.equal(aiMemberAnswerItem.getMemberAnswerQuestionId(),aiMemberAnswerItem.getAnswer()) ? 1 : 2 ); if (aiMemberAnswerItem.getMemberAnswerState() == 2){ aiMemberAnswerItem.setIsCollected(1); }else{ aiMemberAnswerItem.setIsCollected(0); } aiMemberAnswerItemService.updateById(aiMemberAnswerItem); aiMemberAnswer.setDoneCnt(aiMemberAnswer.getDoneCnt() + 1); if (aiMemberAnswerItem.getMemberAnswerState() == 1){ aiMemberAnswer.setCorrectCnt(aiMemberAnswer.getCorrectCnt() + 1); } aiMemberAnswer.setUpdatedTime(createdTime); aiMemberAnswerMapper.updateById(aiMemberAnswer); apiQuestionItemInfoVo.setAnswerAnalysis(aiMemberAnswerItem.getAnswerAnalysis()); apiQuestionItemInfoVo.setMemberAnswerState(aiMemberAnswerItem.getMemberAnswerState()); apiQuestionItemInfoVo.setQuestionCnt(aiMemberAnswer.getQuestionCnt()); apiQuestionItemInfoVo.setDoneCnt(aiMemberAnswer.getDoneCnt()); return new FebsResponse().success().data(apiQuestionItemInfoVo); } @Override public FebsResponse insure(ApiMemberAnswerInsureDto dto) { String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid(); ApiMemberAnswerInsureVo apiMemberAnswerInsureVo = new ApiMemberAnswerInsureVo(); String memberAnswerId = dto.getMemberAnswerId(); AiMemberAnswer aiMemberAnswer = this.getById(memberAnswerId); Integer questionCnt = aiMemberAnswer.getQuestionCnt(); Integer correctCnt = aiMemberAnswer.getCorrectCnt(); Date createdTime = aiMemberAnswer.getCreatedTime(); Date updatedTime = aiMemberAnswer.getUpdatedTime(); apiMemberAnswerInsureVo.setCorrectCnt(correctCnt); BigDecimal divide = new BigDecimal(correctCnt).divide(new BigDecimal(questionCnt), 2, RoundingMode.HALF_DOWN); // 转换为百分比字符串 BigDecimal percentage = divide.multiply(new BigDecimal(100)); String percentageStr = percentage.setScale(2, RoundingMode.HALF_DOWN).toString() + "%"; apiMemberAnswerInsureVo.setCorrectCntPercent(percentageStr); long between = DateUtil.between(createdTime, updatedTime, DateUnit.MINUTE); apiMemberAnswerInsureVo.setUseTime(between); return new FebsResponse().success().data(apiMemberAnswerInsureVo); } @Override public FebsResponse previous(ApiMemberAnswerPreviousDto dto) { String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid(); // 创建分页对象,传入当前页和每页大小 Page page = new Page<>(dto.getPageNow(), dto.getPageSize()); Page pageListByQuery = aiMemberAnswerItemService.getPageListByQuery(page, dto); List records = pageListByQuery.getRecords(); if (CollUtil.isNotEmpty(records)){ ApiMemberAnswerPreviousVo apiMemberAnswerPreviousVo = records.get(0); String memberAnswerId = apiMemberAnswerPreviousVo.getMemberAnswerId(); AiMemberAnswer aiMemberAnswer = this.getById(memberAnswerId); String productId = aiMemberAnswer.getProductId(); AiProduct aiProduct = aiProductService.getById(productId); apiMemberAnswerPreviousVo.setName(aiProduct.getName()); apiMemberAnswerPreviousVo.setQuestionCnt(aiMemberAnswer.getQuestionCnt()); apiMemberAnswerPreviousVo.setDoneCnt(aiMemberAnswer.getDoneCnt()); String productQuestionId = apiMemberAnswerPreviousVo.getProductQuestionId(); AiProductQuestion aiProductQuestion = aiProductQuestionService.getById(productQuestionId); apiMemberAnswerPreviousVo.setTitle(aiProductQuestion.getTitle()); apiMemberAnswerPreviousVo.setDifficulty(aiProductQuestion.getDifficulty()); List answerList = new ArrayList<>(); LambdaQueryWrapper productQuestionItemLambdaQueryWrapper = Wrappers.lambdaQuery(AiProductQuestionItem.class); productQuestionItemLambdaQueryWrapper.eq(AiProductQuestionItem::getProductQuestionId,productQuestionId); productQuestionItemLambdaQueryWrapper.orderByAsc(AiProductQuestionItem::getCreatedTime); List listByQuery = aiProductQuestionItemService.getListByQuery(productQuestionItemLambdaQueryWrapper); if(CollUtil.isNotEmpty(listByQuery)){ for (AiProductQuestionItem aiProductQuestionItem : listByQuery){ ApiMemberAnswerPreviousItemVo apiMemberAnswerPreviousItemVo = new ApiMemberAnswerPreviousItemVo(); apiMemberAnswerPreviousItemVo.setId(aiProductQuestionItem.getId()); apiMemberAnswerPreviousItemVo.setAnswer(aiProductQuestionItem.getAnswer()); apiMemberAnswerPreviousItemVo.setAnswerAnalysis(aiProductQuestionItem.getAnswerAnalysis()); apiMemberAnswerPreviousItemVo.setCorrectAnswer(aiProductQuestionItem.getCorrectAnswer()); answerList.add(apiMemberAnswerPreviousItemVo); } apiMemberAnswerPreviousVo.setAnswerList(answerList); } } return new FebsResponse().success().data(pageListByQuery); } @Override public FebsResponse wrongPage(ApiMemberAnswerWrongPageDto dto) { String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid(); dto.setMemberUuid(memberUuid); return aiMemberAnswerItemService.wrongPage(dto); } @Override public FebsResponse myWork(ApiMemberProductWorkPageDto dto) { String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid(); dto.setMemberUuid(memberUuid); // 创建分页对象,传入当前页和每页大小 Page page = new Page<>(dto.getPageNow(), dto.getPageSize()); Page pageListByQuery = this.getBaseMapper().getPageMyWorkListByQuery(page, dto); return new FebsResponse().success().data(pageListByQuery); } }