From f6ab2c535a9082e8c63d8f5cc12b298aa81087ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E8=89=AF=28004796=29?= Date: Sat, 11 May 2024 12:25:08 +0800 Subject: [PATCH] init --- .../com/ruoyi/test/business/RefreshTest.java | 10 ++ .../com/ruoyi/oss/enums/FileTypeEnums.java | 21 +++ .../ruoyi/xq/constant/RedisHttpConstant.java | 1 + .../controller/app/UserUnreadController.java | 50 +++++++ .../com/ruoyi/xq/domain/CardAuthRecord.java | 4 + .../xq/dto/app/unread/UserUnreadAppVo.java | 15 +++ .../xq/manager/UserUnreadFlagManager.java | 110 ++++++++++++++++ .../xq/service/CardAuthRecordService.java | 4 + .../impl/CardAuthRecordServiceImpl.java | 122 ++++++++++++++++++ .../service/impl/DynamicStarServiceImpl.java | 21 ++- .../xq/service/impl/UserStarServiceImpl.java | 9 +- .../service/impl/UserVisitorServiceImpl.java | 4 + .../ruoyi/xq/tencent/TencentAuthClient.java | 8 +- 13 files changed, 374 insertions(+), 5 deletions(-) create mode 100644 ruoyi-oss/src/main/java/com/ruoyi/oss/enums/FileTypeEnums.java create mode 100644 ruoyi-xq/src/main/java/com/ruoyi/xq/controller/app/UserUnreadController.java create mode 100644 ruoyi-xq/src/main/java/com/ruoyi/xq/dto/app/unread/UserUnreadAppVo.java create mode 100644 ruoyi-xq/src/main/java/com/ruoyi/xq/manager/UserUnreadFlagManager.java diff --git a/ruoyi-admin/src/test/java/com/ruoyi/test/business/RefreshTest.java b/ruoyi-admin/src/test/java/com/ruoyi/test/business/RefreshTest.java index c568424..8b20a4c 100644 --- a/ruoyi-admin/src/test/java/com/ruoyi/test/business/RefreshTest.java +++ b/ruoyi-admin/src/test/java/com/ruoyi/test/business/RefreshTest.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.test.RefreshArea; import com.ruoyi.xq.domain.User; import com.ruoyi.xq.job.JobManager; +import com.ruoyi.xq.service.CardAuthRecordService; import com.ruoyi.xq.service.UserService; import com.ruoyi.xq.util.AgeUtil; import lombok.extern.slf4j.Slf4j; @@ -23,6 +24,15 @@ public class RefreshTest { private JobManager jobManager; @Autowired private UserService userService; + @Autowired + private CardAuthRecordService cardAuthRecordService; + + @Test + public void test() throws InterruptedException { + Long recordId = 1788274531427102721L; + cardAuthRecordService.refreshUserCardByAdmin(recordId); + Thread.sleep(1000000); + } @Test public void refresh(){ diff --git a/ruoyi-oss/src/main/java/com/ruoyi/oss/enums/FileTypeEnums.java b/ruoyi-oss/src/main/java/com/ruoyi/oss/enums/FileTypeEnums.java new file mode 100644 index 0000000..06406b0 --- /dev/null +++ b/ruoyi-oss/src/main/java/com/ruoyi/oss/enums/FileTypeEnums.java @@ -0,0 +1,21 @@ +package com.ruoyi.oss.enums; + +import cn.hutool.http.ContentType; +import lombok.Getter; + +@Getter +public enum FileTypeEnums { + JPG("jpg", ContentType.OCTET_STREAM.getValue()), + MP4("mp4", ContentType.OCTET_STREAM.getValue()); + private final String suffix; + private final String contentType; + + FileTypeEnums(String suffix, String contentType) { + this.suffix = suffix; + this.contentType = contentType; + } + + public String getSuffixV2(){ + return "."+this.getSuffix(); + } +} diff --git a/ruoyi-xq/src/main/java/com/ruoyi/xq/constant/RedisHttpConstant.java b/ruoyi-xq/src/main/java/com/ruoyi/xq/constant/RedisHttpConstant.java index 9aafc4b..cb1c76a 100644 --- a/ruoyi-xq/src/main/java/com/ruoyi/xq/constant/RedisHttpConstant.java +++ b/ruoyi-xq/src/main/java/com/ruoyi/xq/constant/RedisHttpConstant.java @@ -7,6 +7,7 @@ public class RedisHttpConstant { public static final String RESET_PASSWORD_CHECK_REDIS = REDIS_P + "resetPasswordCheck:%s"; public static final String CODE_REDIS = REDIS_P + "codeIncs:%s:%s"; + public static final String USER_UNREAD_REDIS = REDIS_P + "userUnread:%s:%s"; } diff --git a/ruoyi-xq/src/main/java/com/ruoyi/xq/controller/app/UserUnreadController.java b/ruoyi-xq/src/main/java/com/ruoyi/xq/controller/app/UserUnreadController.java new file mode 100644 index 0000000..e93fe44 --- /dev/null +++ b/ruoyi-xq/src/main/java/com/ruoyi/xq/controller/app/UserUnreadController.java @@ -0,0 +1,50 @@ +package com.ruoyi.xq.controller.app; + +import com.ruoyi.common.core.domain.R; +import com.ruoyi.common.helper.LoginHelper; +import com.ruoyi.xq.dto.app.unread.UserUnreadAppVo; +import com.ruoyi.xq.manager.UserUnreadFlagManager; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/user/unread") +@Tag(name = "当前用户未读消息角标") +public class UserUnreadController { + @Autowired + private UserUnreadFlagManager userUnreadFlagManager; + + @GetMapping("/messageNum") + @Operation(summary = "用户未读的数据") + public R messageNum(){ + Long userId = LoginHelper.getUserId(); + UserUnreadAppVo vo = new UserUnreadAppVo(); + vo.setStar(userUnreadFlagManager.getStarFlag(userId)); + vo.setStarDynamic(userUnreadFlagManager.getStarDynamicFlag(userId)); + vo.setVisible(userUnreadFlagManager.getVisibleFlag(userId)); + return R.ok(vo); + } + + @GetMapping("/reset/message") + @Operation(summary = "将消息设置为全部已读") + public R resetMessage(@Parameter(name = "type", description = "类型 1-关注 2-关注动态 3-访问我的人") Integer type){ + Long userId = LoginHelper.getUserId(); + if(type == null){ + return R.ok(); + } + if(type == 1){ + userUnreadFlagManager.resetStarKey(userId); + }else if(type == 2){ + userUnreadFlagManager.resetStarDynamicKey(userId); + }else if(type == 3){ + userUnreadFlagManager.resetVisibleKey(userId); + } + return R.ok(); + } + +} diff --git a/ruoyi-xq/src/main/java/com/ruoyi/xq/domain/CardAuthRecord.java b/ruoyi-xq/src/main/java/com/ruoyi/xq/domain/CardAuthRecord.java index 3bfeb3e..f01585c 100644 --- a/ruoyi-xq/src/main/java/com/ruoyi/xq/domain/CardAuthRecord.java +++ b/ruoyi-xq/src/main/java/com/ruoyi/xq/domain/CardAuthRecord.java @@ -53,6 +53,10 @@ public class CardAuthRecord implements Serializable { * 认证视频 */ private String livenessVideo; + /** + * + */ + private String bestFrame; /** * 身份证正面 */ diff --git a/ruoyi-xq/src/main/java/com/ruoyi/xq/dto/app/unread/UserUnreadAppVo.java b/ruoyi-xq/src/main/java/com/ruoyi/xq/dto/app/unread/UserUnreadAppVo.java new file mode 100644 index 0000000..200c03a --- /dev/null +++ b/ruoyi-xq/src/main/java/com/ruoyi/xq/dto/app/unread/UserUnreadAppVo.java @@ -0,0 +1,15 @@ +package com.ruoyi.xq.dto.app.unread; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class UserUnreadAppVo { + @Schema(description = "关注未读") + private long star; + @Schema(description = "动态关注未读") + private long starDynamic; + @Schema(description = "查看我的人未读") + private long visible; + +} diff --git a/ruoyi-xq/src/main/java/com/ruoyi/xq/manager/UserUnreadFlagManager.java b/ruoyi-xq/src/main/java/com/ruoyi/xq/manager/UserUnreadFlagManager.java new file mode 100644 index 0000000..7da6348 --- /dev/null +++ b/ruoyi-xq/src/main/java/com/ruoyi/xq/manager/UserUnreadFlagManager.java @@ -0,0 +1,110 @@ +package com.ruoyi.xq.manager; + +import com.ruoyi.xq.constant.RedisHttpConstant; +import lombok.Data; +import org.redisson.api.RAtomicLong; +import org.redisson.api.RedissonClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * 用户角标处理 + */ +@Component +public class UserUnreadFlagManager { + + private final static String UNREAD_STAR_FLAG = "star"; + private final static String UNREAD_STAR_DYNAMIC_FLAG = "starDynamic"; + private final static String UNREAD_VISIBLE_FLAG = "visible"; + + @Autowired + private RedissonClient redissonClient; + + private String getStarKey(Long userId){ + return String.format(RedisHttpConstant.USER_UNREAD_REDIS,UNREAD_STAR_FLAG,userId); + } + private String getStarDynamicKey(Long userId){ + return String.format(RedisHttpConstant.USER_UNREAD_REDIS,UNREAD_STAR_DYNAMIC_FLAG,userId); + } + private String getVisibleKey(Long userId){ + return String.format(RedisHttpConstant.USER_UNREAD_REDIS,UNREAD_VISIBLE_FLAG,userId); + } + + public void resetStarKey(Long userId){ + String key = getStarKey(userId); + RAtomicLong atomicLong = redissonClient.getAtomicLong(key); + atomicLong.set(0); + } + public void resetStarDynamicKey(Long userId){ + String key = getStarDynamicKey(userId); + RAtomicLong atomicLong = redissonClient.getAtomicLong(key); + atomicLong.set(0); + } + public void resetVisibleKey(Long userId){ + String key = getVisibleKey(userId); + RAtomicLong atomicLong = redissonClient.getAtomicLong(key); + atomicLong.set(0); + } + + public Long getStarFlag(Long userId){ + String key = getStarKey(userId); + RAtomicLong atomicLong = redissonClient.getAtomicLong(key); + long nn = atomicLong.get(); + if(nn < 0){ + return 0L; + } + return nn; + } + + public Long getStarDynamicFlag(Long userId){ + String key = getStarDynamicKey(userId); + RAtomicLong atomicLong = redissonClient.getAtomicLong(key); + long nn = atomicLong.get(); + if(nn < 0){ + return 0L; + } + return nn; + } + + public Long getVisibleFlag(Long userId){ + String key = getVisibleKey(userId); + RAtomicLong atomicLong = redissonClient.getAtomicLong(key); + long nn = atomicLong.get(); + if(nn < 0){ + return 0L; + } + return nn; + } + + public void star(Long userId){ + String key = getStarKey(userId); + RAtomicLong atomicLong = redissonClient.getAtomicLong(key); + atomicLong.incrementAndGet(); + } + + public void unstar(Long userId){ + String key = getStarKey(userId); + RAtomicLong atomicLong = redissonClient.getAtomicLong(key); + atomicLong.decrementAndGet(); + } + + public void starDynamic(Long userId){ + String key = getStarDynamicKey(userId); + RAtomicLong atomicLong = redissonClient.getAtomicLong(key); + atomicLong.incrementAndGet(); + } + + public void unStarDynamic(Long userId){ + String key = getStarDynamicKey(userId); + RAtomicLong atomicLong = redissonClient.getAtomicLong(key); + atomicLong.incrementAndGet(); + } + + + public void visible(Long userId){ + String key = getVisibleKey(userId); + RAtomicLong atomicLong = redissonClient.getAtomicLong(key); + atomicLong.incrementAndGet(); + } + +} diff --git a/ruoyi-xq/src/main/java/com/ruoyi/xq/service/CardAuthRecordService.java b/ruoyi-xq/src/main/java/com/ruoyi/xq/service/CardAuthRecordService.java index 188ee1b..dd9be96 100644 --- a/ruoyi-xq/src/main/java/com/ruoyi/xq/service/CardAuthRecordService.java +++ b/ruoyi-xq/src/main/java/com/ruoyi/xq/service/CardAuthRecordService.java @@ -17,5 +17,9 @@ public interface CardAuthRecordService extends IService { CommitAuthRecordResp commitAuthRecord(String bizToken); + boolean updateImage(CardAuthRecord cardAuthRecord, GetDetectInfoEnhancedResponse detectInfo); + + boolean refreshUserCardByAdmin(Long authRecordId); + boolean updateCardRecordSuccess(CardAuthRecord cardAuthRecord, GetDetectInfoEnhancedResponse detectInfo); } diff --git a/ruoyi-xq/src/main/java/com/ruoyi/xq/service/impl/CardAuthRecordServiceImpl.java b/ruoyi-xq/src/main/java/com/ruoyi/xq/service/impl/CardAuthRecordServiceImpl.java index cf6f4aa..803b17e 100644 --- a/ruoyi-xq/src/main/java/com/ruoyi/xq/service/impl/CardAuthRecordServiceImpl.java +++ b/ruoyi-xq/src/main/java/com/ruoyi/xq/service/impl/CardAuthRecordServiceImpl.java @@ -1,9 +1,16 @@ package com.ruoyi.xq.service.impl; +import cn.hutool.core.codec.Base64; +import cn.hutool.core.util.IdUtil; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.oss.core.OssClient; +import com.ruoyi.oss.entity.UploadResult; +import com.ruoyi.oss.enums.FileTypeEnums; +import com.ruoyi.oss.factory.OssFactory; import com.ruoyi.xq.domain.AuthOrder; import com.ruoyi.xq.domain.CardAuthRecord; import com.ruoyi.xq.domain.UserAuth; @@ -12,12 +19,14 @@ import com.ruoyi.xq.dto.common.faceauth.CommitAuthRecordResp; import com.ruoyi.xq.enums.common.AuditEnum; import com.ruoyi.xq.enums.face.TokenStatusEnum; import com.ruoyi.xq.enums.pay.PayStatusEnum; +import com.ruoyi.xq.executor.ExecutorConstant; import com.ruoyi.xq.mapper.CardAuthRecordMapper; import com.ruoyi.xq.service.*; import com.ruoyi.xq.tencent.CreateAuthResp; import com.ruoyi.xq.tencent.TencentAuthClient; import com.tencentcloudapi.common.exception.TencentCloudSDKException; import com.tencentcloudapi.faceid.v20180301.models.GetDetectInfoEnhancedResponse; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -29,6 +38,7 @@ import org.springframework.transaction.annotation.Transactional; * @date 2024-04-29 */ @Service +@Slf4j public class CardAuthRecordServiceImpl extends ServiceImpl implements CardAuthRecordService { @Autowired @@ -80,11 +90,123 @@ public class CardAuthRecordServiceImpl extends ServiceImpl { + bean.updateImage(cardAuthRecord,detectInfo); + }); CommitAuthRecordResp commitAuthRecordResp = new CommitAuthRecordResp(); commitAuthRecordResp.setFaceSuccess(success); return commitAuthRecordResp; } + + private String getPath(String userCode,String token,String suffix){ + String uuid = IdUtil.fastSimpleUUID(); + return String.format("cardAuth/%s/%s/%s.%s", userCode, token, uuid, suffix); + } + + @Override + public boolean updateImage(CardAuthRecord cardAuthRecord, GetDetectInfoEnhancedResponse detectInfo){ + OssClient storage = OssFactory.instance(); + String usercode = cardAuthRecord.getUsercode(); + String bizToken = cardAuthRecord.getBizToken(); + CardAuthRecord update = new CardAuthRecord(); + update.setId(cardAuthRecord.getId()); + boolean updateFlag = false; + // 保存身份证 + if(detectInfo.getIdCardData() != null){ + if(StringUtils.isNotBlank(detectInfo.getIdCardData().getOcrFront())){ + try { + byte[] dataByte = Base64.decode(detectInfo.getIdCardData().getOcrFront()); + String path = getPath(usercode, bizToken, FileTypeEnums.JPG.getSuffix()); + UploadResult upload = storage.upload(dataByte, path, FileTypeEnums.JPG.getContentType()); + update.setCardFront(upload.getUrl()); + updateFlag = true; + }catch (Exception e){ + log.error("上传 身份证失败!recordId={}",cardAuthRecord.getId(),e); + } + } + if(StringUtils.isNotBlank(detectInfo.getIdCardData().getOcrBack())){ + try { + byte[] dataByte = Base64.decode(detectInfo.getIdCardData().getOcrBack()); + String path = getPath(usercode, bizToken, FileTypeEnums.JPG.getSuffix()); + UploadResult upload = storage.upload(dataByte, path, FileTypeEnums.JPG.getContentType()); + update.setCardBack(upload.getUrl()); + updateFlag = true; + }catch (Exception e){ + log.error("上传 身份证失败!recordId={}",cardAuthRecord.getId(),e); + } + } + } + if(detectInfo.getBestFrame() != null){ + if(StringUtils.isNotBlank(detectInfo.getBestFrame().getBestFrame())){ + try { + byte[] dataByte = Base64.decode(detectInfo.getBestFrame().getBestFrame()); + String path = getPath(usercode, bizToken, FileTypeEnums.JPG.getSuffix()); + UploadResult upload = storage.upload(dataByte, path, FileTypeEnums.JPG.getContentType()); + update.setBestFrame(upload.getUrl()); + updateFlag = true; + }catch (Exception e){ + log.error("上传 bestFrame 失败!recordId={}",cardAuthRecord.getId(),e); + } + } + } + if(detectInfo.getVideoData() != null){ + if(StringUtils.isNotBlank(detectInfo.getVideoData().getLivenessVideo())){ + try { + byte[] dataByte = Base64.decode(detectInfo.getVideoData().getLivenessVideo()); + String path = getPath(usercode, bizToken, FileTypeEnums.MP4.getSuffix()); + UploadResult upload = storage.upload(dataByte, path, FileTypeEnums.MP4.getContentType()); + update.setLivenessVideo(upload.getUrl()); + updateFlag = true; + }catch (Exception e){ + log.error("上传 视频认证失败!recordId={}",cardAuthRecord.getId(),e); + } + } + } + if(!updateFlag){ + return false; + } + this.updateById(update); + return true; + } + + @Override + public boolean refreshUserCardByAdmin(Long authRecordId){ + CardAuthRecord cardAuthRecord = this.getById(authRecordId); + if(cardAuthRecord == null){ + throw new ServiceException("实名认证不存在!"); + } + GetDetectInfoEnhancedResponse detectInfo = null; + try { + detectInfo = TencentAuthClient.getDetectInfo(cardAuthRecord.getBizToken()); + } catch (TencentCloudSDKException e) { + log.error("查询实名认证异常",e); + throw new ServiceException("实名认证结果获取失败"); + } + boolean pass = TencentAuthClient.faceDetectIsPass(detectInfo); + CardAuthRecord updateRecord = new CardAuthRecord(); + updateRecord.setId(cardAuthRecord.getId()); + if(!pass){ + updateRecord.setTokenStatus(TokenStatusEnum.FAIL.getCode()); + }else{ + updateRecord.setTokenStatus(TokenStatusEnum.SUCCESS.getCode()); + } + if(detectInfo.getText() != null){ + updateRecord.setIdCard(detectInfo.getText().getIdCard()); + updateRecord.setName(detectInfo.getText().getName()); + if(detectInfo.getText().getOcrNation() != null){ + updateRecord.setNation(detectInfo.getText().getOcrNation()+"族"); + } + } + this.updateById(updateRecord); + GetDetectInfoEnhancedResponse finalDetectInfo = detectInfo; + ExecutorConstant.SYNC_EXECUTOR.execute(() -> { + this.updateImage(cardAuthRecord, finalDetectInfo); + }); + return pass; + } + + @Override @Transactional(rollbackFor = Exception.class) public boolean updateCardRecordSuccess(CardAuthRecord cardAuthRecord, GetDetectInfoEnhancedResponse detectInfo){ diff --git a/ruoyi-xq/src/main/java/com/ruoyi/xq/service/impl/DynamicStarServiceImpl.java b/ruoyi-xq/src/main/java/com/ruoyi/xq/service/impl/DynamicStarServiceImpl.java index 5f8a931..e56df06 100644 --- a/ruoyi-xq/src/main/java/com/ruoyi/xq/service/impl/DynamicStarServiceImpl.java +++ b/ruoyi-xq/src/main/java/com/ruoyi/xq/service/impl/DynamicStarServiceImpl.java @@ -4,13 +4,16 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.core.domain.PageQuery; +import com.ruoyi.xq.domain.Dynamic; import com.ruoyi.xq.domain.DynamicImage; import com.ruoyi.xq.domain.DynamicStar; import com.ruoyi.xq.dto.app.dynamic.MyStarDynamicListVO; import com.ruoyi.xq.dto.app.dynamic.MyStarDynamicQuery; import com.ruoyi.xq.dto.common.user.MinUser; +import com.ruoyi.xq.manager.UserUnreadFlagManager; import com.ruoyi.xq.mapper.DynamicStarMapper; import com.ruoyi.xq.service.DynamicImageService; +import com.ruoyi.xq.service.DynamicService; import com.ruoyi.xq.service.DynamicStarService; import com.ruoyi.xq.service.UserService; import org.apache.commons.collections4.CollectionUtils; @@ -36,6 +39,11 @@ public class DynamicStarServiceImpl extends ServiceImpl implements UserStarService { @Autowired private UserService userService; + @Autowired + private UserUnreadFlagManager userUnreadFlagManager; /** * @Schema(description = "1-关注 2-取消关注") */ @@ -54,10 +57,14 @@ public class UserStarServiceImpl extends ServiceImpl im userStar.setStarUserId(starUser.getId()); userStar.setStarUserCode(starUser.getUsercode()); this.save(userStar); + userUnreadFlagManager.star(req.getStarUserId()); }else if(req.getStar().equals(2)){ - this.remove(Wrappers.lambdaQuery(UserStar.class) + boolean flag = this.remove(Wrappers.lambdaQuery(UserStar.class) .eq(UserStar::getUserId, req.getUserId()) .eq(UserStar::getStarUserId, req.getStarUserId())); + if(flag){ + userUnreadFlagManager.unstar(req.getStarUserId()); + } } } diff --git a/ruoyi-xq/src/main/java/com/ruoyi/xq/service/impl/UserVisitorServiceImpl.java b/ruoyi-xq/src/main/java/com/ruoyi/xq/service/impl/UserVisitorServiceImpl.java index a0adce4..a956ddc 100644 --- a/ruoyi-xq/src/main/java/com/ruoyi/xq/service/impl/UserVisitorServiceImpl.java +++ b/ruoyi-xq/src/main/java/com/ruoyi/xq/service/impl/UserVisitorServiceImpl.java @@ -11,6 +11,7 @@ import com.ruoyi.xq.dto.app.userstar.vo.UserStarListVo; import com.ruoyi.xq.dto.app.uservisitor.UserVisitorQuery; import com.ruoyi.xq.dto.app.uservisitor.vo.UserVisitorListVo; import com.ruoyi.xq.lock.LockKey; +import com.ruoyi.xq.manager.UserUnreadFlagManager; import com.ruoyi.xq.mapper.UserVisitorMapper; import com.ruoyi.xq.service.UserService; import com.ruoyi.xq.service.UserVisitorService; @@ -34,6 +35,8 @@ public class UserVisitorServiceImpl extends ServiceImpl