From 8a78b494fbfe1f6b20ae98108d5c411552fa0fc3 Mon Sep 17 00:00:00 2001 From: jiang Date: Sat, 24 Aug 2024 08:55:05 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BA=BA=E8=84=B8=E8=AF=86=E5=88=AB=E4=B8=8E?= =?UTF-8?q?=E5=A4=A7=E6=A8=A1=E5=9E=8B=E9=97=AE=E7=AD=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bonus-modules/bonus-ai/pom.xml | 7 +- .../bonus/ai/controller/FaceController.java | 65 ++++++ .../ai/controller/KnowledgeController.java | 89 ++++++++ .../ai/domain/KnowledgeChatWindowVo.java | 51 +++++ .../bonus/ai/domain/vo/AiQuestionAnswer.java | 48 ++++ .../com/bonus/ai/domain/vo/FaceResultVo.java | 71 ++++++ .../java/com/bonus/ai/domain/vo/FaceVo.java | 62 +++++ .../java/com/bonus/ai/mapper/FaceMapper.java | 60 +++++ .../com/bonus/ai/mapper/KnowledgeMapper.java | 66 ++++++ .../com/bonus/ai/service/FaceService.java | 41 ++++ .../bonus/ai/service/KnowledgeService.java | 60 +++++ .../ai/service/impl/FaceServiceImpl.java | 213 ++++++++++++++++++ .../ai/service/impl/KnowledgeServiceImpl.java | 141 ++++++++++++ .../java/com/bonus/ai/utils/FaceUtils.java | 101 +++++++++ .../main/resources/mapper/ai/FaceMapper.xml | 82 +++++++ .../resources/mapper/ai/KnowledgeMapper.xml | 60 +++++ 16 files changed, 1216 insertions(+), 1 deletion(-) create mode 100644 bonus-modules/bonus-ai/src/main/java/com/bonus/ai/controller/FaceController.java create mode 100644 bonus-modules/bonus-ai/src/main/java/com/bonus/ai/controller/KnowledgeController.java create mode 100644 bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/KnowledgeChatWindowVo.java create mode 100644 bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/vo/AiQuestionAnswer.java create mode 100644 bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/vo/FaceResultVo.java create mode 100644 bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/vo/FaceVo.java create mode 100644 bonus-modules/bonus-ai/src/main/java/com/bonus/ai/mapper/FaceMapper.java create mode 100644 bonus-modules/bonus-ai/src/main/java/com/bonus/ai/mapper/KnowledgeMapper.java create mode 100644 bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/FaceService.java create mode 100644 bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/KnowledgeService.java create mode 100644 bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/impl/FaceServiceImpl.java create mode 100644 bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/impl/KnowledgeServiceImpl.java create mode 100644 bonus-modules/bonus-ai/src/main/java/com/bonus/ai/utils/FaceUtils.java create mode 100644 bonus-modules/bonus-ai/src/main/resources/mapper/ai/FaceMapper.xml create mode 100644 bonus-modules/bonus-ai/src/main/resources/mapper/ai/KnowledgeMapper.xml diff --git a/bonus-modules/bonus-ai/pom.xml b/bonus-modules/bonus-ai/pom.xml index fc0f0c4..3adb592 100644 --- a/bonus-modules/bonus-ai/pom.xml +++ b/bonus-modules/bonus-ai/pom.xml @@ -5,7 +5,7 @@ com.bonus bonus-modules - 24.7.1-SNAPSHOT + 24.7.1 4.0.0 @@ -55,6 +55,11 @@ bonus-common-datasource + + com.bonus + bonus-common-core + + com.bonus diff --git a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/controller/FaceController.java b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/controller/FaceController.java new file mode 100644 index 0000000..4b82324 --- /dev/null +++ b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/controller/FaceController.java @@ -0,0 +1,65 @@ +package com.bonus.ai.controller; + +import com.bonus.ai.domain.vo.FaceVo; +import com.bonus.ai.service.FaceService; +import com.bonus.common.core.web.domain.AjaxResult; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; + +/** + * @author bonus + * 人脸识别控制层 + */ +@RestController +@RequestMapping("/face") +@Slf4j +public class FaceController { + + @Resource + private FaceService faceService; + + + @PostMapping("/getList") + public AjaxResult getList() { + return faceService.getList(); + } + + /** + * 人脸上传 + * + * @param file 人脸图片 + * @param faceVo 人脸信息 + * @return 插入是否成功 + */ + + @PostMapping("/upload") + public AjaxResult upload(MultipartFile file, FaceVo faceVo) { + return faceService.insertFace(file, faceVo); + } + + /** + * 人脸识别 + * + * @param file 人脸图片 + * @return 人脸信息 + */ + @PostMapping("/recognition") + public AjaxResult recognition(MultipartFile file) { + return faceService.recognition(file); + } + + /** + * 识别结果统计 + * + * @return 结果 + */ + @PostMapping("/resultStatistics") + public AjaxResult resultStatistics() { + return faceService.resultStatistics(); + } +} diff --git a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/controller/KnowledgeController.java b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/controller/KnowledgeController.java new file mode 100644 index 0000000..fb5335d --- /dev/null +++ b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/controller/KnowledgeController.java @@ -0,0 +1,89 @@ +package com.bonus.ai.controller; + +import com.bonus.ai.domain.KnowledgeChatWindowVo; +import com.bonus.ai.domain.vo.AiQuestionAnswer; +import com.bonus.ai.service.KnowledgeService; +import com.bonus.common.core.web.domain.AjaxResult; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; + +/** + * @author bonus + */ +@RestController +@RequestMapping("/knowledge") +@Slf4j +public class KnowledgeController { + + @Resource + private KnowledgeService knowledgeService; + + /** + * 获取窗口列表 + * + * @return 集合 + */ + @PostMapping("/getList") + public AjaxResult getList() { + return knowledgeService.getList(); + } + + /** + * 新增窗口 + * + * @return 集合 + */ + @PostMapping("/insertChatWindow") + public AjaxResult insertChatWindow(@RequestBody KnowledgeChatWindowVo knowledgeChatWindowVo) { + return knowledgeService.insertChatWindow(knowledgeChatWindowVo); + } + + /** + * 更新聊天窗口信息 + * + * @param knowledgeChatWindowVo 聊天窗口信息 + * @return 受影响的行数 + */ + @PostMapping("/updateChatWindow") + public AjaxResult updateChatWindow(KnowledgeChatWindowVo knowledgeChatWindowVo) { + return knowledgeService.updateChatWindow(knowledgeChatWindowVo); + } + + /** + * 逻辑删除聊天窗口 + * + * @param windowId 窗口ID + * @return 受影响的行数 + */ + @PostMapping("/deleteChatWindow/{windowId}") + public AjaxResult deleteChatWindow(@PathVariable Long windowId) { + return knowledgeService.deleteChatWindow(windowId); + } + + + /** + * 更新聊天窗口信息 + * + * @param windowId 聊天窗口信息 + * @return 受影响的行数 + */ + @PostMapping("/getAllByWindowId/{windowId}") + public AjaxResult getAllByWindowId(@PathVariable Long windowId) { + return knowledgeService.getAllByWindowId(windowId); + } + + /** + * 逻辑删除聊天窗口 + * + * @param aiQuestionAnswer 问答记录 + * @return 受影响的行数 + */ + @PostMapping("/insertQuestionAnswer") + public AjaxResult insertQuestionAnswer(AiQuestionAnswer aiQuestionAnswer) { + return knowledgeService.insertQuestionAnswer(aiQuestionAnswer); + } + + +} diff --git a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/KnowledgeChatWindowVo.java b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/KnowledgeChatWindowVo.java new file mode 100644 index 0000000..341fc59 --- /dev/null +++ b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/KnowledgeChatWindowVo.java @@ -0,0 +1,51 @@ +package com.bonus.ai.domain; + +import lombok.Data; + +import java.util.Date; + +/** + * @author bonus + * 问答窗口实体类 + */ +@Data +public class KnowledgeChatWindowVo { + /** + * 窗口id + */ + private Long windowId; + /** + * 知识库id + */ + private String knowledgeId; + /** + * 窗口名称 + */ + private String windowName; + /** + * 聊天类型 + */ + private String chatType; + /** + * 客户 + */ + private Long customerId; + /** + * 创建时间 + */ + private Date createTime; + /** + * 更新时间 + */ + private Date updateTime; + /** + * 是否删除 + */ + private String delFlag; + /** + * 备注 + */ + private String remark; + + +} diff --git a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/vo/AiQuestionAnswer.java b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/vo/AiQuestionAnswer.java new file mode 100644 index 0000000..a366c1c --- /dev/null +++ b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/vo/AiQuestionAnswer.java @@ -0,0 +1,48 @@ +package com.bonus.ai.domain.vo; + +import lombok.Data; + +import java.util.Date; + +/** + * @author bonus + */ +@Data +public class AiQuestionAnswer { + /** + * 问答记录ID,主键,自增 + */ + private Long recordId; + /** + * 窗口ID,可为空 + */ + private Long windowId; + /** + * 问题内容,使用长文本 + */ + private String question; + /** + * 回答内容,使用长文本 + */ + private String answer; + /** + * 知识库溯源文档,使用长文本 + */ + private String knowledge; + /** + * 删除标志,0代表存在,2代表删除 + */ + private String delFlag; + /** + * 客户ID,不可为空 + */ + private String customerId; + /** + * 更新时间 + */ + private Date updateTime; + /** + * 备注,最大长度500 + */ + private String remark; +} diff --git a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/vo/FaceResultVo.java b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/vo/FaceResultVo.java new file mode 100644 index 0000000..d36c1d5 --- /dev/null +++ b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/vo/FaceResultVo.java @@ -0,0 +1,71 @@ +package com.bonus.ai.domain.vo; + +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * @author bonus + * 人脸识别调用实体类 + */ +@Data +public class FaceResultVo implements Serializable { + /** + * 结果主键id + */ + private String resultId; + /** + * 人脸库表id + */ + private String faceId; + /** + * 服务id + */ + private String serviceId; + /** + * 识别结果 + */ + private String resultIt; + /** + * 人脸路径 + */ + private String faceAddress; + /** + * 识别时间 + */ + private String recognizeTime; + /** + * 响应时长 + */ + private String responseLong; + /** + * 调用服务IP + */ + private String invokeIp; + /** + * 更新者 + */ + private String updateBy; + /** + * 更新时间 + */ + private String updateTime; + /** + * 是否删除 + */ + private String delFlag; + /** + * 结果类型(0用户登录,1服务注册) + */ + private String resultType; + /** + * 识别状态(0成功,1失败) + */ + private String resultStatus; + /** + * 识别失败原因 + */ + private String failureReason; + +} diff --git a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/vo/FaceVo.java b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/vo/FaceVo.java new file mode 100644 index 0000000..ee4bb4c --- /dev/null +++ b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/vo/FaceVo.java @@ -0,0 +1,62 @@ +package com.bonus.ai.domain.vo; + +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * @author bonus + * 人脸识别实体类 + */ +@Data +public class FaceVo implements Serializable { + /** + * 人脸id + */ + private Long faceId; + /** + * 姓名 + */ + private String name; + /** + * 性别 + */ + private String sex; + /** + * 电话号码 + */ + private String phone; + /** + * 身份证号 + */ + private String idCardNumber; + /** + * 人脸图片路径 + */ + private String faceAddress; + /** + * 人脸特征 + */ + private byte[] feature; + /** + * 创建者 + */ + private String createBy; + /** + * 创建时间 + */ + private Date createTime; + /** + * 更新者 + */ + private String updateBy; + /** + * 更新时间 + */ + private Date updateTime; + /** + * 是否删除 + */ + private String delFlag; +} diff --git a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/mapper/FaceMapper.java b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/mapper/FaceMapper.java new file mode 100644 index 0000000..787dfdf --- /dev/null +++ b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/mapper/FaceMapper.java @@ -0,0 +1,60 @@ +package com.bonus.ai.mapper; + +import com.bonus.ai.domain.vo.FaceResultVo; +import com.bonus.ai.domain.vo.FaceVo; +import feign.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * @author bonus + * 人脸识别mapper层 + */ +@Repository +public interface FaceMapper { + /** + * 查询全部人脸信息 + */ + List getList(); + + /** + * 根据 faceId 判断人脸是否存在 + * + * @param faceId 人脸唯一标识 + * @return 返回 1 表示存在,0 表示不存在 + */ + int existsByFaceId(@Param("faceId") String faceId); + + /** + * 插入人脸信息 + * + * @param face 人脸信息对象 + * @return 受影响的行数 + */ + int insertFace(FaceVo face); + + /** + * 通过身份证id查询人员 + * + * @param idCardNumber 身份证id + * @return 人员信息 + */ + List getFaceByIdCardNumber(String idCardNumber); + + /** + * 插入人脸识别记录 + * + * @param faceResultVo 人脸信息对象 + * @return 受影响的行数 + */ + int insertFaceResult(FaceResultVo faceResultVo); + + /** + * 识别结果统计 + * + * @return 结果 + */ + List resultStatistics(); + +} diff --git a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/mapper/KnowledgeMapper.java b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/mapper/KnowledgeMapper.java new file mode 100644 index 0000000..edc0a29 --- /dev/null +++ b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/mapper/KnowledgeMapper.java @@ -0,0 +1,66 @@ +package com.bonus.ai.mapper; + +import com.bonus.ai.domain.KnowledgeChatWindowVo; +import com.bonus.ai.domain.vo.AiQuestionAnswer; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * Mapper接口,用于操作聊天窗口数据。 + * 提供获取窗口列表、新增、更新、删除窗口的方法。 + * + * @author bonus + */ +@Repository +public interface KnowledgeMapper { + + /** + * 获取窗口列表 + * + * @param userId 用户ID + * @return 包含聊天窗口信息的集合 + */ + List getList(Long userId); + + /** + * 新增窗口 + * + * @param knowledgeChatWindowVo 聊天窗口信息 + * @return 受影响的行数 + */ + int insertChatWindow(KnowledgeChatWindowVo knowledgeChatWindowVo); + + /** + * 更新聊天窗口信息 + * + * @param knowledgeChatWindowVo 聊天窗口信息 + * @return 受影响的行数 + */ + int updateChatWindow(KnowledgeChatWindowVo knowledgeChatWindowVo); + + /** + * 逻辑删除聊天窗口 + * + * @param windowId 窗口ID + * @return 受影响的行数 + */ + int deleteChatWindow(Long windowId); + + + /** + * 根据窗口id获取问答记录 + * + * @return 所有问答记录的列表 + */ + List getAllByWindowId(Long windowId); + + /** + * 插入问答信息 + * + * @param aiQuestionAnswer 问答信息 + * @return 生成的窗口ID + */ + Long insertQuestionAnswer(AiQuestionAnswer aiQuestionAnswer); + +} diff --git a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/FaceService.java b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/FaceService.java new file mode 100644 index 0000000..17bf5bb --- /dev/null +++ b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/FaceService.java @@ -0,0 +1,41 @@ +package com.bonus.ai.service; + +import com.bonus.ai.domain.vo.FaceVo; +import com.bonus.common.core.web.domain.AjaxResult; +import feign.Param; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +/** + * @author bonus + */ +public interface FaceService { + + /** + * 查询全部人脸信息 + */ + AjaxResult getList(); + + /** + * 插入人脸信息 + * + * @param face 人脸信息对象 + * @return 受影响的行数 + */ + AjaxResult insertFace(MultipartFile file, FaceVo face); + + /** + * 人脸识别 + * + * @param file 人脸图片 + * @return 返回人脸信息 + */ + AjaxResult recognition(MultipartFile file); + + /** + * 识别结果统计 + * @return 结果 + */ + AjaxResult resultStatistics(); +} diff --git a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/KnowledgeService.java b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/KnowledgeService.java new file mode 100644 index 0000000..59b1798 --- /dev/null +++ b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/KnowledgeService.java @@ -0,0 +1,60 @@ +package com.bonus.ai.service; + +import com.bonus.ai.domain.KnowledgeChatWindowVo; +import com.bonus.ai.domain.vo.AiQuestionAnswer; +import com.bonus.common.core.web.domain.AjaxResult; + +import java.util.List; + +/** + * @author bonus + */ +public interface KnowledgeService { + /** + * 获取窗口列表 + * + * @return 集合 + */ + AjaxResult getList(); + + /** + * 新增窗口 + * + * @return 集合 + */ + AjaxResult insertChatWindow(KnowledgeChatWindowVo knowledgeChatWindowVo); + + + /** + * 更新聊天窗口信息 + * + * @param knowledgeChatWindowVo 聊天窗口信息 + * @return 受影响的行数 + */ + AjaxResult updateChatWindow(KnowledgeChatWindowVo knowledgeChatWindowVo); + + /** + * 逻辑删除聊天窗口 + * + * @param windowId 窗口ID + * @return 受影响的行数 + */ + AjaxResult deleteChatWindow(Long windowId); + + + /** + * 根据窗口id获取问答记录 + * + * @return 所有问答记录的列表 + */ + AjaxResult getAllByWindowId(Long windowId); + + /** + * 插入问答信息 + * + * @param aiQuestionAnswer 问答信息 + * @return 生成的窗口ID + */ + AjaxResult insertQuestionAnswer(AiQuestionAnswer aiQuestionAnswer); + +} diff --git a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/impl/FaceServiceImpl.java b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/impl/FaceServiceImpl.java new file mode 100644 index 0000000..13e1512 --- /dev/null +++ b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/impl/FaceServiceImpl.java @@ -0,0 +1,213 @@ +package com.bonus.ai.service.impl; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.bonus.ai.domain.vo.FaceVo; +import com.bonus.ai.mapper.FaceMapper; +import com.bonus.ai.service.FaceService; +import com.bonus.ai.utils.FaceUtils; +import com.bonus.common.core.web.domain.AjaxResult; +import com.bonus.common.security.utils.SecurityUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; + +/** + * @author bonus + * 人脸识别服务层 + */ +@Service +public class FaceServiceImpl implements FaceService { + + @Resource + private FaceMapper faceMapper; + + /** + * 查询全部人脸信息 + */ + @Override + public AjaxResult getList() { + return AjaxResult.success(faceMapper.getList()); + } + + /** + * 插入人脸信息 + * + * @param face 人脸信息对象 + * @return 受影响的行数 + */ + @Override + public AjaxResult insertFace(MultipartFile file, FaceVo face) { + if (isFileOrFaceInvalid(file, face)) { + return AjaxResult.error("文件或人员信息不能为空, 请检查输入"); + } + try { + String base64WithMimeType = getBase64WithMimeType(file); + String response = FaceUtils.updateDb(base64WithMimeType, "add", face.getIdCardNumber()); + return handleInsertResponse(file, response, face, base64WithMimeType); + } catch (Exception e) { + return AjaxResult.error("插入人脸信息失败"); + } + } + + /** + * 人脸识别 + * + * @param file + * @return + */ + @Override + public AjaxResult recognition(MultipartFile file) { + if (ObjectUtils.isEmpty(file)) { + return AjaxResult.error("文件不能为空, 请选择文件"); + } + + try { + String base64WithMimeType = getBase64WithMimeType(file); + String response = FaceUtils.faceRecognition(base64WithMimeType); + return handleRecognitionResponse(response); + } catch (Exception e) { + return AjaxResult.error("人脸识别失败"); + } + } + + /** + * 识别结果统计 + * + * @return 结果 + */ + @Override + public AjaxResult resultStatistics() { + return AjaxResult.success(faceMapper.resultStatistics()); + } + + /** + * 判断文件的 MIME 类型是否为图片类型 + */ + private boolean isImageMimeType(String mimeType) { + Set validMimeTypes = new HashSet<>(); + validMimeTypes.add("image/jpeg"); + validMimeTypes.add("image/png"); + return mimeType != null && validMimeTypes.contains(mimeType); + } + + /** + * 检查文件和人员信息是否为空 + */ + private boolean isFileOrFaceInvalid(MultipartFile file, FaceVo face) { + return ObjectUtils.isEmpty(file) || + ObjectUtils.isEmpty(face.getName()) || + ObjectUtils.isEmpty(face.getIdCardNumber()); + } + + /** + * 获取Base64编码的文件内容,并添加MIME类型 + */ + private String getBase64WithMimeType(MultipartFile file) throws Exception { + String mimeType = file.getContentType(); + if (!isImageMimeType(mimeType)) { + throw new IllegalArgumentException("文件类型不支持,请上传图片文件"); + } + + byte[] fileBytes = file.getBytes(); + String base64String = Base64.getEncoder().encodeToString(fileBytes); + return "data:" + mimeType + ";base64," + base64String; + } + + /** + * 处理插入人脸信息的响应 + */ + private AjaxResult handleInsertResponse(MultipartFile file, String response, FaceVo face, String base64WithMimeType) { + if (response == null) return AjaxResult.error(); + JSONObject jsonObject = JSON.parseObject(response); + String code = jsonObject.getString("code"); + switch (code) { + case "30002": + face.setCreateTime(new Date()); + face.setCreateBy(SecurityUtils.getUsername()); + face.setUpdateBy(SecurityUtils.getUsername()); + face.setUpdateTime(new Date()); + try { + // 设置保存文件的目录,这里假设是在应用程序的根目录下的uploads文件夹 + String uploadDir = "uploads"; + Path uploadPath = Paths.get(uploadDir); + // 如果目录不存在,则创建 + if (!Files.exists(uploadPath)) { + Files.createDirectories(uploadPath); + } + byte[] bytes = file.getBytes(); + String fileName = UUID.randomUUID() + file.getOriginalFilename(); + String filePath = Paths.get("uploads").toAbsolutePath().normalize().toString() + File.separator + fileName; + java.nio.file.Files.write(java.nio.file.Paths.get(filePath), bytes); + face.setFaceAddress(filePath); + } catch (Exception e) { + return AjaxResult.error(); + } + return faceMapper.insertFace(face) > 0 ? AjaxResult.success() : AjaxResult.error(); + case "30006": + return AjaxResult.error("文件类型不支持"); + case "30007": + return AjaxResult.error("不支持的操作类型"); + case "30008": + return AjaxResult.error("存在多张人脸"); + case "30009": + return AjaxResult.error("光照条件差"); + case "30010": + case "30011": + return AjaxResult.error("人脸不全"); + case "30019": + return AjaxResult.error("人员信息已存在"); + case "30018": + return AjaxResult.error("未检测到人脸"); + default: + return AjaxResult.error(); + } + } + + /** + * 处理人脸识别的响应 + */ + private AjaxResult handleRecognitionResponse(String response) { + if (response == null) { + return AjaxResult.error(); + } + JSONObject jsonObject = JSON.parseObject(response); + String code = jsonObject.getString("code"); + switch (code) { + case "30000": + JSONArray dataArray = jsonObject.getJSONArray("data"); + String idCardNumber = dataArray.getString(0); + List faceByIdCardNumber = faceMapper.getFaceByIdCardNumber(idCardNumber); + return faceByIdCardNumber != null && !faceByIdCardNumber.isEmpty() + ? AjaxResult.success(faceByIdCardNumber.get(0)) + : AjaxResult.error("人员不存在"); + case "30001": + return AjaxResult.error("人员不存在"); + case "30006": + return AjaxResult.error("文件类型不支持"); + case "30007": + return AjaxResult.error("不支持的操作类型"); + case "30008": + return AjaxResult.error("存在多张人脸"); + case "30009": + return AjaxResult.error("光照条件差"); + case "30010": + case "30011": + return AjaxResult.error("人脸不全"); + case "30019": + return AjaxResult.error("人员信息已存在"); + case "30018": + return AjaxResult.error("未检测到人脸"); + default: + return AjaxResult.error(); + } + } +} diff --git a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/impl/KnowledgeServiceImpl.java b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/impl/KnowledgeServiceImpl.java new file mode 100644 index 0000000..d0ebf0d --- /dev/null +++ b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/impl/KnowledgeServiceImpl.java @@ -0,0 +1,141 @@ +package com.bonus.ai.service.impl; + +import com.bonus.ai.domain.KnowledgeChatWindowVo; +import com.bonus.ai.domain.vo.AiQuestionAnswer; +import com.bonus.ai.mapper.KnowledgeMapper; +import com.bonus.ai.service.KnowledgeService; +import com.bonus.common.core.web.domain.AjaxResult; +import com.bonus.common.security.utils.SecurityUtils; +import io.swagger.models.auth.In; +import org.apache.commons.lang3.ObjectUtils; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Date; +import java.util.List; + +/** + * @author bonus + */ +@Service +public class KnowledgeServiceImpl implements KnowledgeService { + + @Resource + private KnowledgeMapper knowledgeMapper; + + /** + * 获取窗口列表 + * + * @return 集合 + */ + @Override + public AjaxResult getList() { + Long userId = SecurityUtils.getUserId(); + try { + return AjaxResult.success(knowledgeMapper.getList(userId)); + } catch (Exception e) { + return AjaxResult.error(); + } + } + + /** + * 新增窗口 + * + * @param knowledgeChatWindowVo 实体 + * @return 集合 + */ + @Override + public AjaxResult insertChatWindow(KnowledgeChatWindowVo knowledgeChatWindowVo) { + try { + knowledgeChatWindowVo.setWindowName(knowledgeChatWindowVo.getWindowName()); + knowledgeChatWindowVo.setCustomerId(SecurityUtils.getUserId()); + knowledgeChatWindowVo.setCreateTime(new Date()); + knowledgeChatWindowVo.setUpdateTime(new Date()); + int l = knowledgeMapper.insertChatWindow(knowledgeChatWindowVo); + if (l > 0) { + return AjaxResult.success(); + } else { + return AjaxResult.error(); + } + } catch (Exception e) { + return AjaxResult.error(); + } + } + + /** + * 更新聊天窗口信息 + * + * @param knowledgeChatWindowVo 聊天窗口信息 + * @return 受影响的行数 + */ + @Override + public AjaxResult updateChatWindow(KnowledgeChatWindowVo knowledgeChatWindowVo) { + try { + int i = knowledgeMapper.updateChatWindow(knowledgeChatWindowVo); + if (i > 0) { + return AjaxResult.success(); + } else { + return AjaxResult.error(); + } + } catch (Exception e) { + return AjaxResult.error(); + } + } + + /** + * 逻辑删除聊天窗口 + * + * @param windowId 窗口ID + * @return 受影响的行数 + */ + @Override + public AjaxResult deleteChatWindow(Long windowId) { + try { + int i = knowledgeMapper.deleteChatWindow(windowId); + if (i > 0) { + return AjaxResult.success(); + } else { + return AjaxResult.error(); + } + + } catch (Exception e) { + return AjaxResult.error(); + } + } + + /** + * 根据窗口id获取问答记录 + * + * @param windowId 窗口id + * @return 所有问答记录的列表 + */ + @Override + public AjaxResult getAllByWindowId(Long windowId) { + try { + List allByWindowId = knowledgeMapper.getAllByWindowId(windowId); + return AjaxResult.success(allByWindowId); + } catch (Exception e) { + return AjaxResult.error(); + } + } + + /** + * 插入问答信息 + * + * @param aiQuestionAnswer 问答信息 + * @return 生成的窗口ID + */ + @Override + public AjaxResult insertQuestionAnswer(AiQuestionAnswer aiQuestionAnswer) { + try { + Long l = knowledgeMapper.insertQuestionAnswer(aiQuestionAnswer); + if (ObjectUtils.isEmpty(l)) { + return AjaxResult.error(); + } else { + return AjaxResult.success(l); + } + } catch (Exception e) { + return AjaxResult.error(); + } + } +} diff --git a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/utils/FaceUtils.java b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/utils/FaceUtils.java new file mode 100644 index 0000000..1b5851d --- /dev/null +++ b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/utils/FaceUtils.java @@ -0,0 +1,101 @@ +package com.bonus.ai.utils; + + +import com.alibaba.fastjson2.JSON; +import com.bonus.common.core.utils.http.HttpRequestHelper; + +import java.util.HashMap; +import java.util.Map; + +/** + * 人脸识别工具类 + * + * @author bonus + */ +public class FaceUtils { + /** + * ip + */ + private static final String IP = "192.168.0.14"; + /** + * 端口 + */ + private static final String PORT = "18017"; + + // 接口路径常量 + private static final String UPDATE_DB = "/updatedb"; + private static final String REFRESH_DB = "/refreshdb"; + private static final String FACE_RECOGNITION = "/facerecognition"; + private static final String FEATURE_DETECT = "/featuredetect"; + + /** + * 获取完整的接口 URL + * + * @return 完整的 URL + */ + private static String getFullUrl() { + return new StringBuilder() + .append("http://") + .append(IP) + .append(":") + .append(PORT) + .toString(); + } + + /** + * @param img 图片的本地路径 or base64编码 or url + * @param optMode ”add”:添加人脸图片;”delete”:删除人脸图片;”replace”:替换已有人脸图片; + * @param uniqueKey 指定要操作的这个人脸的名字 + * @return 字符串 + */ + public static String updateDb(String img, String optMode, String uniqueKey) { + Map headers = new HashMap<>(); + Map params = new HashMap(); + params.put("img", img); + params.put("optMode", optMode); + params.put("uniqueKey", uniqueKey); + String json = JSON.toJSONString(params); + return HttpRequestHelper.postJson(getFullUrl(), UPDATE_DB, json, headers); + } + + /** + * 刷新人脸库 + * + * @return 返回请求体 + */ + + public static String refreshDb() { + Map headers = new HashMap<>(); + return HttpRequestHelper.postJson(getFullUrl(), REFRESH_DB, "", headers); + } + + /** + * 对输入人脸进行识别 + * + * @param img 图片的本地路径 or base64编码 or url + * @return 人脸信息 + */ + public static String faceRecognition(String img) { + Map headers = new HashMap<>(); + Map params = new HashMap(); + params.put("img", img); + String json = JSON.toJSONString(params); + return HttpRequestHelper.postJson(getFullUrl(), FACE_RECOGNITION, json, headers); + } + + /** + * 对输入人脸进行特征提取 + * + * @param img 图片的本地路径 or base64编码 or url + * @return 人脸信息 + */ + public static String featureDetect(String img) { + Map params = new HashMap(); + Map headers = new HashMap<>(); + params.put("img", img); + String json = JSON.toJSONString(params); + return HttpRequestHelper.postJson(getFullUrl(), FEATURE_DETECT, json, headers); + } + + +} diff --git a/bonus-modules/bonus-ai/src/main/resources/mapper/ai/FaceMapper.xml b/bonus-modules/bonus-ai/src/main/resources/mapper/ai/FaceMapper.xml new file mode 100644 index 0000000..f0a0006 --- /dev/null +++ b/bonus-modules/bonus-ai/src/main/resources/mapper/ai/FaceMapper.xml @@ -0,0 +1,82 @@ + + + + + + + INSERT INTO ai_face_databse (name, sex, phone, idcard_number, + face_address, create_by, create_time, + update_by, update_time) + VALUES ( #{name}, #{sex}, #{phone}, #{idCardNumber}, + #{faceAddress}, #{createBy}, #{createTime}, + #{updateBy}, #{updateTime}) + + + insert into ai_facerecognize_result (face_id, service_id, result_it, face_address, recognize_time, + response_long, invoke_ip, update_by, update_time, result_type, + result_status, failure_reason) + values (#{faceId}, #{serviceId}, #{resultIt}, #{faceAddress}, #{recognizeTime}, #{responseLong}, #{invokeIp}, + #{updateBy}, #{updateTime}, #{resultType}, #{resultStatus}, #{failureReason}); + + + + + + + + + + + + + + diff --git a/bonus-modules/bonus-ai/src/main/resources/mapper/ai/KnowledgeMapper.xml b/bonus-modules/bonus-ai/src/main/resources/mapper/ai/KnowledgeMapper.xml new file mode 100644 index 0000000..aee8384 --- /dev/null +++ b/bonus-modules/bonus-ai/src/main/resources/mapper/ai/KnowledgeMapper.xml @@ -0,0 +1,60 @@ + + + + + insert into ai_chat_window (knowledge_id, window_name, chat_type, customer_id, create_time, + update_time, remark) + values (#{knowledgeId}, #{windowName}, #{chatType}, #{customerId}, now(), now(), #{remark}); + + + INSERT INTO ai_question_answer + (window_id, question, answer, knowledge, del_flag, customer_id, update_time, remark) + VALUES (#{windowId}, #{question}, #{answer}, #{knowledge}, #{delFlag}, #{customerId}, #{updateTime}, #{remark}); + + + + + + + update ai_chat_window + set window_name = #{windowName}, + chat_type = #{chatType}, + update_time = now(), + remark = #{remark} + where window_id = #{windowId}; + + + + update ai_chat_window + set del_flag = '1', + update_time = now() + where window_id = #{windowId}; + +