src/main/java/cc/mrbird/febs/ai/controller/member/ApiMemberController.java
New file @@ -0,0 +1,43 @@ package cc.mrbird.febs.ai.controller.member; import cc.mrbird.febs.ai.req.member.ApiMemberPageDto; import cc.mrbird.febs.ai.req.memberPoint.ApiMemberPointDto; import cc.mrbird.febs.ai.res.member.ApiMemberPageVo; import cc.mrbird.febs.ai.res.memberAnswer.ApiMemberAnswerVoV2; import cc.mrbird.febs.ai.service.AiMemberService; import cc.mrbird.febs.common.entity.FebsResponse; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author Administrator */ @Slf4j @Validated @RestController @RequiredArgsConstructor @RequestMapping(value = "/api/ai/member") @Api(value = "ApiMemberController", tags = "AI-用户") public class ApiMemberController { private final AiMemberService aiMemberService; @ApiOperation(value = "我的团队", notes = "我的团队") @ApiResponses({ @ApiResponse(code = 200, message = "success", response = ApiMemberPageVo.class) }) @PostMapping(value = "/myTeam") public FebsResponse myTeam(@RequestBody @Validated ApiMemberPageDto dto) { return aiMemberService.myTeam(dto); } } src/main/java/cc/mrbird/febs/ai/controller/memberPoint/ApiMemberPointController.java
New file @@ -0,0 +1,40 @@ package cc.mrbird.febs.ai.controller.memberPoint; import cc.mrbird.febs.ai.req.memberAnswer.*; import cc.mrbird.febs.ai.req.memberPoint.ApiMemberPointDto; import cc.mrbird.febs.ai.res.memberAnswer.*; import cc.mrbird.febs.ai.service.AiMemberAnswerService; import cc.mrbird.febs.ai.service.AiMemberPointService; import cc.mrbird.febs.common.entity.FebsResponse; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author Administrator */ @Slf4j @Validated @RestController @RequiredArgsConstructor @RequestMapping(value = "/api/ai/memberPoint") @Api(value = "ApiMemberPointController", tags = "AI-用户学习") public class ApiMemberPointController { private final AiMemberPointService aiMemberPointService; @ApiOperation(value = "学习时长保存", notes = "学习时长保存") @PostMapping(value = "/saveTime") public FebsResponse saveTime(@RequestBody @Validated ApiMemberPointDto dto) { return aiMemberPointService.saveTime(dto); } } src/main/java/cc/mrbird/febs/ai/controller/memberTalk/ApiMemberTalkStreamController.java
@@ -2,25 +2,18 @@ import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkItemPageDto; import cc.mrbird.febs.ai.req.memberTalkStream.*; import cc.mrbird.febs.ai.req.talk.AiTalkAnswerStream; import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkItemVo; import cc.mrbird.febs.ai.res.memberTalkStream.ApiMemberTalkReloadStreamVo; import cc.mrbird.febs.ai.res.memberTalkStream.ApiMemberTalkStreamVo; import cc.mrbird.febs.ai.service.ApiMemberTalkStreamService; import cc.mrbird.febs.ai.strategy.enumerates.LlmStrategyEnum; import cc.mrbird.febs.ai.strategy.param.LlmStrategyDto; import cc.mrbird.febs.ai.service.AiMemberTalkStreamService; import cc.mrbird.febs.common.entity.FebsResponse; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.dashscope.common.Role; import io.swagger.annotations.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Flux; import java.util.ArrayList; /** * @author Administrator @@ -33,7 +26,7 @@ @Api(value = "ApiMemberTalkStreamController", tags = "AI-用户陪练(流式)") public class ApiMemberTalkStreamController { private final ApiMemberTalkStreamService apiMemberTalkStreamService; private final AiMemberTalkStreamService aiMemberTalkStreamService; @ApiOperation("生成题目") @ApiResponses({ @@ -41,7 +34,7 @@ }) @PostMapping("/start") public FebsResponse start(@RequestBody @Validated ApiMemberTalkStreamDto dto) { return apiMemberTalkStreamService.start(dto); return aiMemberTalkStreamService.start(dto); } @ApiOperation(value = "再练一次(重新回答)", notes = "再练一次(重新回答)") @@ -51,7 +44,7 @@ @PostMapping(value = "/reload") public FebsResponse reload(@RequestBody @Validated ApiMemberTalkReloadStreamDto dto) { return apiMemberTalkStreamService.reload(dto); return aiMemberTalkStreamService.reload(dto); } @ApiOperation(value = "对话记录分页查询", notes = "对话记录分页查询") @@ -61,14 +54,14 @@ @PostMapping(value = "/historyPage") public FebsResponse historyPage(@RequestBody @Validated ApiMemberTalkItemPageDto dto) { return apiMemberTalkStreamService.historyPage(dto); return aiMemberTalkStreamService.historyPage(dto); } @ApiOperation(value = "保存用户回答", notes = "保存答案") @PostMapping(value = "/saveMemberAnswer") public FebsResponse saveMemberAnswer(@RequestBody @Validated ApiMemberTalkMemberAnswerSavaDto dto) { return apiMemberTalkStreamService.saveMemberAnswer(dto); return aiMemberTalkStreamService.saveMemberAnswer(dto); } @ApiOperation("回答(流式)") @@ -80,7 +73,7 @@ if (StrUtil.isEmpty(dto.getId()) || StrUtil.isEmpty(dto.getReqContext())|| StrUtil.isEmpty(dto.getReqContext())){ return Flux.just(new FebsResponse().fail().message("参数异常")); } return apiMemberTalkStreamService.answer(dto); return aiMemberTalkStreamService.answer(dto); } @ApiOperation("回答(流式)") @@ -92,14 +85,14 @@ if (StrUtil.isEmpty(dto.getId()) || StrUtil.isEmpty(dto.getReqContext())|| StrUtil.isEmpty(dto.getReqContext())){ return Flux.just(new FebsResponse().fail().message("参数异常")); } return apiMemberTalkStreamService.answerV2(dto); return aiMemberTalkStreamService.answerV2(dto); } @ApiOperation(value = "保存AI回答", notes = "保存AI回答") @PostMapping(value = "/saveAnswer") public FebsResponse saveAnswer(@RequestBody @Validated ApiMemberTalkAnswerSavaDto dto) { return apiMemberTalkStreamService.saveAnswer(dto); return aiMemberTalkStreamService.saveAnswer(dto); } } src/main/java/cc/mrbird/febs/ai/controller/product/ApiProductController.java
@@ -27,7 +27,7 @@ @RestController @RequiredArgsConstructor @RequestMapping(value = "/api/ai/product") @Api(value = "ApiProductController", tags = "AI-产品") @Api(value = "ApiProductController", tags = "AI-产品(培训)") public class ApiProductController { private final AiProductService aiProductService; src/main/java/cc/mrbird/febs/ai/controller/productPoint/ApiProductPointController.java
@@ -30,7 +30,7 @@ @RestController @RequiredArgsConstructor @RequestMapping(value = "/api/ai/productPoint") @Api(value = "ApiProductPointController", tags = "AI-产品知识点") @Api(value = "ApiProductPointController", tags = "AI-知识点(学习)") public class ApiProductPointController { private final AiProductPointService aiProductPointService; src/main/java/cc/mrbird/febs/ai/req/member/ApiMemberPageDto.java
New file @@ -0,0 +1,23 @@ package cc.mrbird.febs.ai.req.member; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotNull; @Data @ApiModel(value = "ApiMemberPageDto", description = "参数") public class ApiMemberPageDto { @NotNull(message = "页码不能为空") @ApiModelProperty(value = "页码", example = "1") private Integer pageNow; @NotNull(message = "每页数量不能为空") @ApiModelProperty(value = "每页数量", example = "10") private Integer pageSize; @ApiModelProperty(hidden = true) private String memberUuid; } src/main/java/cc/mrbird/febs/ai/req/memberPoint/ApiMemberPointDto.java
New file @@ -0,0 +1,23 @@ package cc.mrbird.febs.ai.req.memberPoint; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.Min; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; @Data @ApiModel(value = "ApiMemberPointDto", description = "参数") public class ApiMemberPointDto { @NotBlank(message = "知识点ID不能为空") @ApiModelProperty(value = "知识点ID") private String productPointId; @NotNull(message = "时长不能为空") @Min(value = 1, message = "时长不能小于1") @ApiModelProperty(value = "时长") private Integer totalTime; } src/main/java/cc/mrbird/febs/ai/req/productPoint/ApiProductPointPageDto.java
@@ -24,4 +24,7 @@ @ApiModelProperty(value = "公司ID", example = "123") private String companyId; @ApiModelProperty(value = "角色ID", example = "123") private String memberRoleId; } src/main/java/cc/mrbird/febs/ai/res/member/ApiMemberPageVo.java
New file @@ -0,0 +1,25 @@ package cc.mrbird.febs.ai.res.member; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data @ApiModel(value = "ApiMemberPageVo", description = "参数") public class ApiMemberPageVo { @ApiModelProperty(value = "用户ID") private String memberUuid; @ApiModelProperty(value = "微信名") private String nickName; @ApiModelProperty(value = "用户姓名") private String memberName; @ApiModelProperty(value = "联系次数") private Integer practiceCnt; @ApiModelProperty(value = "学习时长") private Integer studyTime; } src/main/java/cc/mrbird/febs/ai/service/AiMemberPointService.java
New file @@ -0,0 +1,18 @@ package cc.mrbird.febs.ai.service; import cc.mrbird.febs.ai.entity.AiMemberPoint; import cc.mrbird.febs.ai.req.memberPoint.ApiMemberPointDto; import cc.mrbird.febs.common.entity.FebsResponse; import com.baomidou.mybatisplus.extension.service.IService; public interface AiMemberPointService extends IService<AiMemberPoint> { AiMemberPoint getById(String id); AiMemberPoint add(String memberUuid, String productPointId, String companyId, Integer totalTime); FebsResponse saveTime(ApiMemberPointDto dto); } src/main/java/cc/mrbird/febs/ai/service/AiMemberService.java
@@ -1,9 +1,13 @@ package cc.mrbird.febs.ai.service; import cc.mrbird.febs.ai.entity.AiMember; import cc.mrbird.febs.ai.req.member.ApiMemberPageDto; import cc.mrbird.febs.common.entity.FebsResponse; import com.baomidou.mybatisplus.extension.service.IService; public interface AiMemberService extends IService<AiMember> { AiMember getById(String id); FebsResponse myTeam(ApiMemberPageDto dto); } src/main/java/cc/mrbird/febs/ai/service/AiMemberTalkService.java
@@ -9,6 +9,7 @@ import reactor.core.publisher.Flux; import java.util.Date; import java.util.List; import java.util.function.Consumer; /** @@ -39,4 +40,6 @@ FebsResponse historyPage(ApiMemberTalkItemPageDto dto); Flux<FebsResponse> answerStream(String question); List<AiMemberTalk> getListByCompanyId(String companyId); } src/main/java/cc/mrbird/febs/ai/service/AiMemberTalkStreamService.java
File was renamed from src/main/java/cc/mrbird/febs/ai/service/ApiMemberTalkStreamService.java @@ -9,7 +9,7 @@ import java.util.Date; public interface ApiMemberTalkStreamService extends IService<AiMemberTalk> { public interface AiMemberTalkStreamService extends IService<AiMemberTalk> { /** * 生成题目(流式) * @param dto src/main/java/cc/mrbird/febs/ai/service/impl/AiMemberPointServiceImpl.java
New file @@ -0,0 +1,67 @@ package cc.mrbird.febs.ai.service.impl; import cc.mrbird.febs.ai.entity.AiMemberPoint; import cc.mrbird.febs.ai.mapper.AiMemberPointMapper; import cc.mrbird.febs.ai.req.memberPoint.ApiMemberPointDto; import cc.mrbird.febs.ai.service.AiMemberPointService; 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.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.Date; @Slf4j @Service @RequiredArgsConstructor public class AiMemberPointServiceImpl extends ServiceImpl<AiMemberPointMapper, AiMemberPoint> implements AiMemberPointService { private final AiMemberPointMapper aiMemberPointMapper; @Override public AiMemberPoint getById(String id) { return aiMemberPointMapper.selectById( id); } @Override public AiMemberPoint add(String memberUuid, String productPointId, String companyId, Integer totalTime) { AiMemberPoint aiMemberPoint = new AiMemberPoint(); aiMemberPoint.setId(UUID.getSimpleUUIDString()); aiMemberPoint.setCreatedTime(new Date()); aiMemberPoint.setMemberId(memberUuid); aiMemberPoint.setProductPointId(productPointId); aiMemberPoint.setCompanyId(companyId); aiMemberPoint.setTotalTime(totalTime); aiMemberPointMapper.insert(aiMemberPoint); return aiMemberPoint; } @Override public FebsResponse saveTime(ApiMemberPointDto dto) { String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid(); String companyId = LoginUserUtil.getLoginUser().getCompanyId(); String productPointId = dto.getProductPointId(); Integer totalTime = dto.getTotalTime(); AiMemberPoint aiMemberPoint = this.getById(productPointId); if (ObjectUtil.isNull(aiMemberPoint)){ aiMemberPoint = this.add(memberUuid, productPointId, companyId, totalTime); }else{ Integer oldTotalTime = aiMemberPoint.getTotalTime(); aiMemberPointMapper.update( null, Wrappers.lambdaUpdate(AiMemberPoint.class) .set(AiMemberPoint::getTotalTime,oldTotalTime + totalTime) .set(AiMemberPoint::getUpdatedTime,new Date()) .eq(AiMemberPoint::getId,aiMemberPoint.getId()) ); } return new FebsResponse().success(); } } src/main/java/cc/mrbird/febs/ai/service/impl/AiMemberServiceImpl.java
@@ -1,12 +1,30 @@ package cc.mrbird.febs.ai.service.impl; import cc.mrbird.febs.ai.entity.AiMember; import cc.mrbird.febs.ai.entity.AiMemberTalk; import cc.mrbird.febs.ai.mapper.AiMemberMapper; import cc.mrbird.febs.ai.req.member.ApiMemberPageDto; import cc.mrbird.febs.ai.res.member.ApiMemberPageVo; import cc.mrbird.febs.ai.service.AiMemberService; import cc.mrbird.febs.ai.service.AiMemberTalkService; import cc.mrbird.febs.common.entity.FebsResponse; import cc.mrbird.febs.common.utils.LoginUserUtil; import cc.mrbird.febs.mall.entity.MallMember; import cc.mrbird.febs.mall.mapper.MallMemberMapper; import cn.hutool.core.collection.CollUtil; 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 java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; /** * @author Administrator @@ -17,8 +35,67 @@ public class AiMemberServiceImpl extends ServiceImpl<AiMemberMapper, AiMember> implements AiMemberService { private final AiMemberMapper aiMemberMapper; private final MallMemberMapper mallMemberMapper; private final AiMemberTalkService aiMemberTalkService; @Override public AiMember getById(String id) { return aiMemberMapper.selectById( id); } @Override public FebsResponse myTeam(ApiMemberPageDto dto) { List<ApiMemberPageVo> objects = new ArrayList<>(); String companyId = LoginUserUtil.getLoginUser().getCompanyId(); // 创建分页对象,传入当前页和每页大小 Page<AiMember> page = new Page<>(dto.getPageNow(), dto.getPageSize()); LambdaQueryWrapper<AiMember> queryWrapper = Wrappers.lambdaQuery(AiMember.class); queryWrapper.eq(AiMember::getCompanyId, companyId); Page<AiMember> pageListByQuery = aiMemberMapper.selectPage(page, queryWrapper); List<AiMember> records = pageListByQuery.getRecords(); if (CollUtil.isNotEmpty( records)){ objects = buildMemberPages(companyId,records,objects); } return new FebsResponse().success().data(objects); } private List<ApiMemberPageVo> buildMemberPages(String companyId,List<AiMember> records,List<ApiMemberPageVo> objects) { /** * 获取用户信息 */ //stream流操作records,获取全部的id Set<String> memberIds = records.stream().map(AiMember::getId).collect(Collectors.toSet()); List<MallMember> mallMembers = mallMemberMapper.selectList( Wrappers.lambdaQuery(MallMember.class) .select(MallMember::getMemberUuid, MallMember::getName, MallMember::getRealName) .in(MallMember::getMemberUuid, memberIds) .eq(MallMember::getCompanyId, companyId) ); //Stream流操作mallMembers,获取一个map<memberUuid,mallMember>的对象 Map<String, MallMember> mallMemberMap = mallMembers.stream().collect(Collectors.toMap(MallMember::getMemberUuid, mallMember -> mallMember)); /** * 获取用户联系次数 * ai陪练 * ai答题 */ List<AiMemberTalk> aiMemberTalks = aiMemberTalkService.getListByCompanyId(companyId); //Stream流操作aiMemberTalks,获取一个map<memberUuid,aiMemberTalk>的对象 for (AiMember aiMember : records){ ApiMemberPageVo apiMemberPageVo = new ApiMemberPageVo(); apiMemberPageVo.setMemberUuid(aiMember.getId()); //判断mallMemberMap中是否存在该会员 apiMemberPageVo.setMemberName(mallMemberMap.containsKey(aiMember.getId()) ? mallMemberMap.get(aiMember.getId()).getName() : ""); apiMemberPageVo.setNickName(mallMemberMap.containsKey(aiMember.getId()) ? mallMemberMap.get(aiMember.getId()).getName() : ""); objects.add(apiMemberPageVo); } return objects; } } src/main/java/cc/mrbird/febs/ai/service/impl/AiMemberTalkServiceImpl.java
@@ -293,4 +293,12 @@ return aiService.answerStream(question); } @Override public List<AiMemberTalk> getListByCompanyId(String companyId) { return aiMemberTalkMapper.selectList( Wrappers.lambdaQuery(AiMemberTalk.class) .eq(AiMemberTalk::getCompanyId, companyId) ); } } src/main/java/cc/mrbird/febs/ai/service/impl/AiMemberTalkStreamServiceImpl.java
File was renamed from src/main/java/cc/mrbird/febs/ai/service/impl/ApiMemberTalkStreamServiceImpl.java @@ -41,7 +41,7 @@ @Slf4j @Service @RequiredArgsConstructor public class ApiMemberTalkStreamServiceImpl extends ServiceImpl<AiMemberTalkMapper, AiMemberTalk> implements ApiMemberTalkStreamService { public class AiMemberTalkStreamServiceImpl extends ServiceImpl<AiMemberTalkMapper, AiMemberTalk> implements AiMemberTalkStreamService { private final AiMemberTalkMapper aiMemberTalkMapper; private final AiProductRoleLinkService aiProductRoleLinkService; src/main/java/cc/mrbird/febs/ai/service/impl/AiProductPointServiceImpl.java
@@ -42,6 +42,7 @@ private final AiProductPointMapper aiProductPointMapper; private final AiProductPointLinkService aiProductPointLinkService; private final AiProductCategoryService aiProductCategoryService; private final AiMemberRoleService aiMemberRoleService; @Override public AiProductPoint getById(String id) { @@ -81,6 +82,11 @@ @Override public FebsResponse productPointList(ApiProductPointPageDto dto) { if(StrUtil.isEmpty(dto.getMemberRoleId())){ String memberRoleId = aiMemberRoleService.getDefaultMemberRoleId(); dto.setMemberRoleId(memberRoleId); } if(StrUtil.isEmpty(dto.getCategoryId())){ String categoryId = aiProductCategoryService.getDefaultProductCategoryId(); dto.setCategoryId(categoryId); src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java
@@ -749,6 +749,7 @@ mallMember.setCompanyId(aiMember.getCompanyId()); } mallMember.setInviteId(inviteId); mallMember.setName("新用户"+inviteId); this.baseMapper.updateById(mallMember); MallMemberWallet wallet = new MallMemberWallet(); wallet.setBalance(BigDecimal.ZERO); src/main/resources/mapper/modules/AiProductPointMapper.xml
@@ -19,6 +19,11 @@ <if test="record.companyId != null and record.companyId != ''"> and a.company_id = #{record.companyId} </if> <if test="record.memberRoleId != null and record.memberRoleId != ''"> and a.id in ( select product_point_id from ai_member_role_point where role_id = #{record.memberRoleId} ) </if> </if> </where> order by a.CREATED_TIME asc