From 9570d4dad234246671c14f1ebf64b6a2022edf73 Mon Sep 17 00:00:00 2001 From: khy <2908249413@qq.com> Date: Fri, 6 Jun 2025 13:05:13 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=A2=E6=9C=8D=E7=BB=91=E5=AE=9A=E7=94=A8?= =?UTF-8?q?=E6=88=B7,=E4=B8=80=E5=AF=B9=E5=A4=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../supportstaff/SupportStaffForm.vue | 54 ++++++++++++++- .../promotion/api/kefu/SupportStaffApi.java | 13 ++++ .../api/kefu/dto/SupportStaffDTO.java | 66 +++++++++++++++++++ .../promotion/enums/ErrorCodeConstants.java | 2 + .../api/kefu/SupportStaffApiImpl.java | 38 +++++++++++ .../kefu/vo/message/KeFuMessageListReqVO.java | 34 ++++++++++ .../supportstaff/vo/SupportStaffRespVO.java | 4 +- .../vo/SupportStaffSaveReqVO.java | 5 +- .../app/circle/AppCircleController.java | 15 +++++ .../app/kefu/AppKeFuMessageController.java | 62 ++++++++++++++++- .../vo/message/AppKeFuMessageSendReqVO.java | 10 ++- .../supportstaff/SupportStaffDO.java | 7 +- .../kefu/KeFuConversationServiceImpl.java | 19 +++++- .../service/kefu/KeFuMessageService.java | 5 +- .../service/kefu/KeFuMessageServiceImpl.java | 50 ++++++++++++-- .../supportstaff/SupportStaffService.java | 3 +- .../supportstaff/SupportStaffServiceImpl.java | 27 +++++++- .../order/vo/AppTradeOrderPageItemRespVO.java | 6 ++ .../vo/item/AppTradeOrderItemRespVO.java | 4 ++ .../dataobject/order/TradeOrderItemDO.java | 5 ++ .../app/user/AppMemberUserController.java | 26 +++++++- .../app/user/vo/AppMemberUserInfoRespVO.java | 9 +++ 22 files changed, 444 insertions(+), 20 deletions(-) create mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/kefu/SupportStaffApi.java create mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/kefu/dto/SupportStaffDTO.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/kefu/SupportStaffApiImpl.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/message/KeFuMessageListReqVO.java diff --git a/yudao-admin-vue3/src/views/mall/promotion/supportstaff/SupportStaffForm.vue b/yudao-admin-vue3/src/views/mall/promotion/supportstaff/SupportStaffForm.vue index 5af56d3..da1af44 100644 --- a/yudao-admin-vue3/src/views/mall/promotion/supportstaff/SupportStaffForm.vue +++ b/yudao-admin-vue3/src/views/mall/promotion/supportstaff/SupportStaffForm.vue @@ -9,6 +9,26 @@ > + + + + + + + @@ -65,6 +85,7 @@ \ No newline at end of file + + diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/kefu/SupportStaffApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/kefu/SupportStaffApi.java new file mode 100644 index 0000000..da99f03 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/kefu/SupportStaffApi.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.module.promotion.api.kefu; + +import cn.iocoder.yudao.module.promotion.api.kefu.dto.SupportStaffDTO; + +public interface SupportStaffApi { + /** + * 获得 skuId 商品匹配的的限时折扣信息 + * @return 限时折扣信息 + */ + SupportStaffDTO getUserIsSupportStaff(Long userId); + + Integer getUnredCount(); +} diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/kefu/dto/SupportStaffDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/kefu/dto/SupportStaffDTO.java new file mode 100644 index 0000000..83f90fb --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/kefu/dto/SupportStaffDTO.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.module.promotion.api.kefu.dto; + +import lombok.Data; + +/** + * 客服人员 DO + * + * @author 管理员 + */ +@Data +public class SupportStaffDTO { + + /** + * ID + */ + private Integer id; + /** + * 客服名称 + */ + private String name; + /** + * 客服头像 + */ + private String pic; + /** + * 手机号码 + */ + private String phone; + /** + * 登录账号 + */ + private String account; + /** + * 登录密码 + */ + private String password; + /** + * 客服状态 + * + * 枚举 {@link TODO kefu_support_staff_status 对应的类} + */ + private Integer status; + /** + * 手机订单管理 + * + * 枚举 {@link TODO kefu_support_staff_order_manage 对应的类} + */ + private Integer orderManage; + /** + * 订单通知 + * + * 枚举 {@link TODO kefu_support_staff_order_inform 对应的类} + */ + private Integer orderInform; + + /* + * 线上状态 + * */ + private Integer lineStatus; + + /* + * 用户id + * */ + private Long userId; + +} diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java index 88dd670..de3fa95 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java @@ -173,4 +173,6 @@ public interface ErrorCodeConstants { ErrorCode REGISTRATION_NOT_EXISTS = new ErrorCode(1_024_000_000, "活动报名不存在"); ErrorCode ACTIVITY_INFO_NOT_EXISTS = new ErrorCode(1_025_000_000, "活动信息不存在"); + + ErrorCode SUPPORT_STAFF_USER_EXISTS = new ErrorCode(1_026_000_000, "客服人员绑定的用户已存在"); } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/kefu/SupportStaffApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/kefu/SupportStaffApiImpl.java new file mode 100644 index 0000000..19e6ee2 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/kefu/SupportStaffApiImpl.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.promotion.api.kefu; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.promotion.api.kefu.dto.SupportStaffDTO; + +import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuConversationDO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.supportstaff.SupportStaffDO; +import cn.iocoder.yudao.module.promotion.service.kefu.KeFuConversationService; +import cn.iocoder.yudao.module.promotion.service.supportstaff.SupportStaffService; + +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.List; + +@Service +@Validated +public class SupportStaffApiImpl implements SupportStaffApi{ + @Resource + private SupportStaffService staffService; + @Resource + private KeFuConversationService conversationService; + @Override + public SupportStaffDTO getUserIsSupportStaff(Long userId) { + SupportStaffDO staffDO = staffService.getSupportStaffByUserId(userId); + return BeanUtils.toBean(staffDO, SupportStaffDTO.class); + } + + @Override + public Integer getUnredCount() { + List conversationDOS = conversationService.getKefuConversationList(null); + int totalAge = conversationDOS.stream() + .mapToInt(KeFuConversationDO::getAdminUnreadMessageCount) // 将Person对象转换为int(即age值)的Stream + .sum(); // 对所有age值进行累加 + return totalAge; + } +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/message/KeFuMessageListReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/message/KeFuMessageListReqVO.java new file mode 100644 index 0000000..dcb4e4c --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/message/KeFuMessageListReqVO.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 客服消息列表 Request VO") +@Data +public class KeFuMessageListReqVO { + + private static final Integer LIMIT = 10; + + @Schema(description = "会话编号", example = "12580") + @NotNull(message = "会话编号不能为空") + private Long conversationId; + + @Schema(description = "发送时间", example = "2024-03-27 12:00:00") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime createTime; + + @Schema(description = "每次查询条数,最大值为 100", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @NotNull(message = "每次查询条数不能为空") + @Min(value = 1, message = "每次查询条数最小值为 1") + @Max(value = 100, message = "每次查询最大值为 100") + private Integer limit = LIMIT; + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/supportstaff/vo/SupportStaffRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/supportstaff/vo/SupportStaffRespVO.java index cbba878..4c94f20 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/supportstaff/vo/SupportStaffRespVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/supportstaff/vo/SupportStaffRespVO.java @@ -56,5 +56,7 @@ public class SupportStaffRespVO { private LocalDateTime createTime; private Integer lineStatus; + @Schema(description = "用户id") + private Long userId; -} \ No newline at end of file +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/supportstaff/vo/SupportStaffSaveReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/supportstaff/vo/SupportStaffSaveReqVO.java index a5e5659..313f240 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/supportstaff/vo/SupportStaffSaveReqVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/supportstaff/vo/SupportStaffSaveReqVO.java @@ -41,4 +41,7 @@ public class SupportStaffSaveReqVO { private Integer lineStatus; -} \ No newline at end of file + @Schema(description = "用户id") + private Long userId; + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/circle/AppCircleController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/circle/AppCircleController.java index 1cb7d76..e41cf63 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/circle/AppCircleController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/circle/AppCircleController.java @@ -63,6 +63,21 @@ public class AppCircleController { return success(result); } + @GetMapping("/getById") + @Operation(summary = "获得动态对象") + @PreAuthenticated + public CommonResult getCircleById(@RequestParam("id") Long id) { + CircleDO circleDO = circleService.getCircle(id); + + CircleRespVO circleRespVO = BeanUtils.toBean(circleDO, CircleRespVO.class); + List listCircleReviewByCircleId = circleReviewService.getListCircleReviewByCircleId(circleRespVO.getId()); + for (CircleReviewDO reviewDO : listCircleReviewByCircleId) { + reviewDO.setRemark(utilMethod(reviewDO.getUserId(),reviewDO.getReplyUserId())); + } + circleRespVO.setCircleList(listCircleReviewByCircleId); + return success(circleRespVO); + } + @PostMapping("/create") @Operation(summary = "发表社区动态") @PreAuthenticated diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/AppKeFuMessageController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/AppKeFuMessageController.java index ab0a5c9..6b83c76 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/AppKeFuMessageController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/AppKeFuMessageController.java @@ -7,6 +7,8 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; import cn.iocoder.yudao.module.member.api.user.MemberUserApi; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.conversation.KeFuConversationRespVO; +import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageListReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageRespVO; import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessagePageReqVO; import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessageSendReqVO; @@ -15,17 +17,30 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.supportstaff.SupportStaffDO; import cn.iocoder.yudao.module.promotion.dal.mysql.kefu.KeFuConversationMapper; import cn.iocoder.yudao.module.promotion.dal.mysql.supportstaff.SupportStaffMapper; +import cn.iocoder.yudao.module.promotion.service.kefu.KeFuConversationService; import cn.iocoder.yudao.module.promotion.service.kefu.KeFuMessageService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; 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.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @Tag(name = "用户 APP - 客服消息") @@ -46,12 +61,25 @@ public class AppKeFuMessageController { @Resource private SupportStaffMapper supportStaffMapper; + @Resource + private KeFuConversationService conversationService; + + @Resource + private AdminUserApi adminUserApi; + @PostMapping("/send") @Operation(summary = "发送客服消息") @PreAuthenticated public CommonResult sendKefuMessage(@Valid @RequestBody AppKeFuMessageSendReqVO sendReqVO) { - sendReqVO.setSenderId(getLoginUserId()).setSenderType(UserTypeEnum.MEMBER.getValue()); // 设置用户编号和类型 + SupportStaffDO supportStaffDO = supportStaffMapper.selectOne(new LambdaQueryWrapper() + .eq(SupportStaffDO::getUserId, getLoginUserId())); + if (supportStaffDO != null && supportStaffDO.getStatus() == 1){ + sendReqVO.setSenderId(Long.valueOf(supportStaffDO.getId())).setSenderType(UserTypeEnum.ADMIN.getValue()); // 设置用户编号和类型 + } + else { + sendReqVO.setSenderId(getLoginUserId()).setSenderType(UserTypeEnum.MEMBER.getValue()); // 设置用户编号和类型 + } return success(kefuMessageService.sendKefuMessage(sendReqVO)); } @@ -98,4 +126,34 @@ public class AppKeFuMessageController { return true; } -} \ No newline at end of file + @GetMapping("/listCoversation") + @Operation(summary = "获得客服会话列表") + @PreAuthenticated + public CommonResult> getConversationList() { + // 查询会话列表 + List respList = BeanUtils.toBean(conversationService.getKefuConversationList(null), + KeFuConversationRespVO.class); + + // 拼接数据 + Map userMap = memberUserApi.getUserMap(convertSet(respList, KeFuConversationRespVO::getUserId)); + respList.forEach(item -> findAndThen(userMap, item.getUserId(), + memberUser -> item.setUserAvatar(memberUser.getAvatar()).setUserNickname(memberUser.getNickname()))); + return success(respList); + } + + @GetMapping("/listMessgaebyCoversation") + @Operation(summary = "获取聊天列表") + @PreAuthenticated + public CommonResult> getKeFuMessageList(@Valid KeFuMessageListReqVO pageReqVO) { + // 获得数据 + List list = kefuMessageService.getKeFuMessageList(pageReqVO); + + // 拼接数据 + List result = BeanUtils.toBean(list, KeFuMessageRespVO.class); + Map userMap = adminUserApi.getUserMap(convertSet(filterList(result, + item -> UserTypeEnum.ADMIN.getValue().equals(item.getSenderType())), KeFuMessageRespVO::getSenderId)); + result.forEach(item -> findAndThen(userMap, item.getSenderId(), user -> item.setSenderAvatar(user.getAvatar()))); + return success(result); + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/vo/message/AppKeFuMessageSendReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/vo/message/AppKeFuMessageSendReqVO.java index bc25fa6..0daf261 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/vo/message/AppKeFuMessageSendReqVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/vo/message/AppKeFuMessageSendReqVO.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -24,4 +25,11 @@ public class AppKeFuMessageSendReqVO { @Schema(description = "发送人类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1", hidden = true) private Integer senderType; -} \ No newline at end of file + + @Schema(description = "接收人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24571", hidden = true) + private Long receiverId; + + @Schema(description = "接收人类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "24571", hidden = true) + private Integer receiverType; + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/supportstaff/SupportStaffDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/supportstaff/SupportStaffDO.java index 529dd93..e85d4ee 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/supportstaff/SupportStaffDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/supportstaff/SupportStaffDO.java @@ -68,4 +68,9 @@ public class SupportStaffDO extends BaseDO { */ private Integer lineStatus; -} \ No newline at end of file + /* + * 用户id + * */ + private Long userId; + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuConversationServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuConversationServiceImpl.java index 0a9ffd0..2b8d763 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuConversationServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuConversationServiceImpl.java @@ -2,7 +2,9 @@ package cn.iocoder.yudao.module.promotion.service.kefu; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.conversation.KeFuConversationUpdatePinnedReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.supportstaff.vo.SupportStaffPageReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuConversationDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.supportstaff.SupportStaffDO; @@ -100,13 +102,24 @@ public class KeFuConversationServiceImpl implements KeFuConversationService { @Override public KeFuConversationDO getOrCreateConversation(Long userId) { KeFuConversationDO conversation = conversationMapper.selectOne(KeFuConversationDO::getUserId, userId); + //查询当前后台默认客服 + Long kefuId = null; + SupportStaffPageReqVO vo = new SupportStaffPageReqVO(); + vo.setStatus(1); + PageResult pageResult = supportStaffMapper.selectPage(vo); + if (null!=pageResult&&pageResult.getTotal()>=1) + kefuId=Long.valueOf(pageResult.getList().get(0).getId()); // 没有历史会话,则初始化一个新会话 if (conversation == null) { conversation = new KeFuConversationDO().setUserId(userId).setLastMessageTime(LocalDateTime.now()) .setLastMessageContent(StrUtil.EMPTY).setLastMessageContentType(KeFuMessageContentTypeEnum.TEXT.getType()) .setAdminPinned(Boolean.FALSE).setUserDeleted(Boolean.FALSE).setAdminDeleted(Boolean.FALSE) - .setAdminUnreadMessageCount(0); - conversationMapper.insert(conversation); + .setAdminUnreadMessageCount(0).setKefuId(kefuId); + if (userId == null) { + conversation = null; + }else { + conversationMapper.insert(conversation); + } } return conversation; } @@ -140,4 +153,4 @@ public class KeFuConversationServiceImpl implements KeFuConversationService { return supportStaffDO.getName(); } -} \ No newline at end of file +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuMessageService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuMessageService.java index 81aa0b3..b4ad4ce 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuMessageService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuMessageService.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.promotion.service.kefu; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageListReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessagePageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageSendReqVO; import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessagePageReqVO; @@ -8,6 +9,7 @@ import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuM import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO; import javax.validation.Valid; +import java.util.List; import java.util.Optional; /** @@ -73,4 +75,5 @@ public interface KeFuMessageService { */ Boolean getLatestMessageBySenderId(Integer senderId); -} \ No newline at end of file + List getKeFuMessageList(KeFuMessageListReqVO pageReqVO); +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuMessageServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuMessageServiceImpl.java index 8ab0ac1..c976269 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuMessageServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuMessageServiceImpl.java @@ -8,9 +8,12 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi; import cn.iocoder.yudao.module.member.api.user.MemberUserApi; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageListReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessagePageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageSendReqVO; import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessagePageReqVO; @@ -29,6 +32,7 @@ import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyMessageDO; import cn.iocoder.yudao.module.system.dal.mysql.notify.NotifyMessageMapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -42,6 +46,7 @@ import java.util.concurrent.ConcurrentMap; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.KEFU_CONVERSATION_NOT_EXISTS; import static cn.iocoder.yudao.module.promotion.enums.WebSocketMessageTypeConstants.KEFU_MESSAGE_ADMIN_READ; import static cn.iocoder.yudao.module.promotion.enums.WebSocketMessageTypeConstants.KEFU_MESSAGE_TYPE; @@ -107,10 +112,27 @@ public class KeFuMessageServiceImpl implements KeFuMessageService { public Long sendKefuMessage(AppKeFuMessageSendReqVO sendReqVO) { //用户发消息 // 1.1 设置会话编号 KeFuMessageDO kefuMessage = BeanUtils.toBean(sendReqVO, KeFuMessageDO.class); - KeFuConversationDO conversation = conversationService.getOrCreateConversation(sendReqVO.getSenderId()); + //判断是否是客服 + SupportStaffDO staff = supportStaffMapper.selectOne(new LambdaUpdateWrapper() + .eq(SupportStaffDO::getUserId,getLoginUserId())); + //判断客服标志 + int a = 0; + KeFuConversationDO conversation = new KeFuConversationDO(); + if (staff != null && staff.getStatus() == 1){ + conversation = conversationService.getOrCreateConversation(sendReqVO.getReceiverId()); + if (conversation == null){ + return 5L; + } + a = 1; + }else { + conversation = conversationService.getOrCreateConversation(sendReqVO.getSenderId()); + kefuMessage.setReceiverId(conversation.getUserId()).setReceiverType(UserTypeEnum.MEMBER.getValue()); + } + +// KeFuConversationDO conversation = conversationService.getOrCreateConversation(sendReqVO.getSenderId()); kefuMessage.setConversationId(conversation.getId()); // 1.2 保存消息 - kefuMessage.setReceiverId(conversation.getKefuId()).setReceiverType(UserTypeEnum.ADMIN.getValue()); // 设置接收人 +// kefuMessage.setReceiverId(conversation.getKefuId()).setReceiverType(UserTypeEnum.ADMIN.getValue()); // 设置接收人 keFuMessageMapper.insert(kefuMessage); // 2. 更新会话消息冗余 @@ -121,7 +143,7 @@ public class KeFuMessageServiceImpl implements KeFuMessageService { //判断客服是否在线,自动回复 SupportStaffDO supportStaffDO = supportStaffMapper.selectOne("id", conversation.getKefuId()); - if (supportStaffDO.getLineStatus() == 2){ //离线 + if (supportStaffDO.getLineStatus() == 2 && a == 0){ //离线 KeFuConfigurationDO type = keFuConfigurationMapper.selectOne("type", 1); if (type != null){ //是否配置了客服不在线回复 if (type.getFeedback() != null){ @@ -140,7 +162,10 @@ public class KeFuMessageServiceImpl implements KeFuMessageService { } } } - + //判断是否是客服 + if (null!=staff&&staff.getStatus()==1) { + getSelf().sendAsyncMessageToMember(sendReqVO.getReceiverId(), KEFU_MESSAGE_TYPE, kefuMessage); + } // 3. 通知所有管理员更新对话 getSelf().sendAsyncMessageToAdmin(KEFU_MESSAGE_TYPE, kefuMessage); return kefuMessage.getId(); @@ -227,6 +252,11 @@ public class KeFuMessageServiceImpl implements KeFuMessageService { @Override public PageResult getKeFuMessagePage(AppKeFuMessagePageReqVO pageReqVO, Long userId) { + //判断是否是客服 + SupportStaffDO staff = supportStaffMapper.selectOne((new LambdaQueryWrapperX() + .eq(SupportStaffDO::getUserId, userId))); + if (null==staff) { +// conversationService.getConversation(pageReqVO.getConversationId()); // 1. 获得客服会话 KeFuConversationDO conversation = conversationService.getConversationByUserId(userId); if (conversation == null) { @@ -234,6 +264,7 @@ public class KeFuMessageServiceImpl implements KeFuMessageService { } // 2. 设置会话编号 pageReqVO.setConversationId(conversation.getId()); + } return keFuMessageMapper.selectPage(pageReqVO); } @@ -255,4 +286,13 @@ public class KeFuMessageServiceImpl implements KeFuMessageService { return SpringUtil.getBean(getClass()); } -} \ No newline at end of file + @Override + public List getKeFuMessageList(KeFuMessageListReqVO pageReqVO) { + return keFuMessageMapper.selectList(new QueryWrapperX() + .eqIfPresent("conversation_id",pageReqVO.getConversationId()) + .ltIfPresent("create_time",pageReqVO.getCreateTime()) + .orderByDesc("create_time") + .limitN(pageReqVO.getLimit())); + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/supportstaff/SupportStaffService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/supportstaff/SupportStaffService.java index 482e8d2..32e6a6c 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/supportstaff/SupportStaffService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/supportstaff/SupportStaffService.java @@ -55,4 +55,5 @@ public interface SupportStaffService { */ void updateLineStatus(String id , Integer lineStatus ); -} \ No newline at end of file + SupportStaffDO getSupportStaffByUserId(Long userId); +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/supportstaff/SupportStaffServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/supportstaff/SupportStaffServiceImpl.java index 583c702..755b464 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/supportstaff/SupportStaffServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/supportstaff/SupportStaffServiceImpl.java @@ -8,6 +8,9 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.supportstaff.SupportStaf import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.promotion.dal.mysql.supportstaff.SupportStaffMapper; + +import java.util.List; + import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; @@ -27,6 +30,12 @@ public class SupportStaffServiceImpl implements SupportStaffService { public Integer createSupportStaff(SupportStaffSaveReqVO createReqVO) { // 插入 SupportStaffDO supportStaff = BeanUtils.toBean(createReqVO, SupportStaffDO.class); + if(supportStaff.getUserId() != null){ + SupportStaffDO staffDO = supportStaffMapper.selectOne("user_id", supportStaff.getUserId()); + if(staffDO != null){ + throw exception(SUPPORT_STAFF_USER_EXISTS); + } + } supportStaff.setLineStatus(2); supportStaffMapper.insert(supportStaff); // 返回 @@ -39,6 +48,17 @@ public class SupportStaffServiceImpl implements SupportStaffService { validateSupportStaffExists(updateReqVO.getId()); // 更新 SupportStaffDO updateObj = BeanUtils.toBean(updateReqVO, SupportStaffDO.class); + + SupportStaffDO supportStaffDO = supportStaffMapper.selectOne("id", updateReqVO.getId()); + //判断用户是否被绑定 + if (updateObj.getUserId() != null){ + if (supportStaffDO.getUserId() == null || !supportStaffDO.getUserId().equals(updateObj.getUserId())){ + SupportStaffDO staffDO = supportStaffMapper.selectOne("user_id", updateObj.getUserId()); + if(staffDO != null){ + throw exception(SUPPORT_STAFF_USER_EXISTS); + } + } + } supportStaffMapper.updateById(updateObj); } @@ -73,4 +93,9 @@ public class SupportStaffServiceImpl implements SupportStaffService { supportStaffMapper.updateById(supportStaffDO); } -} \ No newline at end of file + @Override + public SupportStaffDO getSupportStaffByUserId(Long userId) { + return supportStaffMapper.selectOne("user_id", userId); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderPageItemRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderPageItemRespVO.java index ba7b813..45b7c64 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderPageItemRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderPageItemRespVO.java @@ -55,4 +55,10 @@ public class AppTradeOrderPageItemRespVO { @Schema(description = "拼团记录编号", example = "100") private Long combinationRecordId; + @Schema(description = "代理商id", example = "25514") + private Long agentId; + + @Schema(description = "发票状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer invoiceStatus; + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/item/AppTradeOrderItemRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/item/AppTradeOrderItemRespVO.java index 98d1820..44093fa 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/item/AppTradeOrderItemRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/item/AppTradeOrderItemRespVO.java @@ -58,4 +58,8 @@ public class AppTradeOrderItemRespVO { @Schema(description = "售后状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Integer afterSaleStatus; + @Schema(description = "代理商id", example = "25514") + private Long agentId; + + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java index ed1bef3..e06a3d8 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java @@ -177,6 +177,11 @@ public class TradeOrderItemDO extends BaseDO { */ private Integer afterSaleStatus; + /* + * 代理商户id + * */ + private Long agentId; + /** * 商品属性 */ diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java index a8284a2..6ec5f77 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java @@ -34,6 +34,8 @@ import cn.iocoder.yudao.module.member.service.transfer.TransferService; import cn.iocoder.yudao.module.member.service.transferlog.TransferLogService; import cn.iocoder.yudao.module.member.service.user.MemberUserService; import cn.iocoder.yudao.module.member.service.user.PaidMemberUserService; +import cn.iocoder.yudao.module.promotion.api.kefu.SupportStaffApi; +import cn.iocoder.yudao.module.promotion.api.kefu.dto.SupportStaffDTO; import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO; import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageUserService; import io.swagger.v3.oas.annotations.Operation; @@ -82,6 +84,9 @@ public class AppMemberUserController { private MemberCodeMapper memberCodeMapper; @Resource private PaidMemberUserService paidMemberUserService; + @Resource + private SupportStaffApi supportStaffApi; + @GetMapping("/get") @Operation(summary = "获得基本信息") @PreAuthenticated @@ -89,10 +94,27 @@ public class AppMemberUserController { MemberUserDO user = userService.getUser(getLoginUserId()); MemberLevelDO level = levelService.getLevel(user.getLevelId()); PaidMemberUserDO paidMemberUserDO = paidMemberUserService.getPaidMemberUserByUid(getLoginUserId()); + AppMemberUserInfoRespVO appMemberUserInfoRespVO = new AppMemberUserInfoRespVO(); + //判断是否是客服 + SupportStaffDTO supportStaffDTO = supportStaffApi.getUserIsSupportStaff(getLoginUserId()); if (paidMemberUserDO == null) { - return success(MemberUserConvert.INSTANCE.convert(user, level,null,null)); + appMemberUserInfoRespVO = MemberUserConvert.INSTANCE.convert(user, level,null,null); + if (null!=supportStaffDTO&&supportStaffDTO.getStatus()==1) { + appMemberUserInfoRespVO.setIdKefu(true); + appMemberUserInfoRespVO.setKefuPic(supportStaffDTO.getPic()); + appMemberUserInfoRespVO.setUnreadCount(supportStaffApi.getUnredCount()); + } + return success(appMemberUserInfoRespVO); +// return success(MemberUserConvert.INSTANCE.convert(user, level,null,null)); } - return success(MemberUserConvert.INSTANCE.convert(user, level,paidMemberUserDO.getPayMemberType(),paidMemberUserDO.getCardExpirationTime())); + appMemberUserInfoRespVO = MemberUserConvert.INSTANCE.convert(user, level,paidMemberUserDO.getPayMemberType(),paidMemberUserDO.getCardExpirationTime()); + if (null!=supportStaffDTO&&supportStaffDTO.getStatus()==1) { + appMemberUserInfoRespVO.setIdKefu(true); + appMemberUserInfoRespVO.setKefuPic(supportStaffDTO.getPic()); + appMemberUserInfoRespVO.setUnreadCount(supportStaffApi.getUnredCount()); + } + return success(appMemberUserInfoRespVO); +// return success(MemberUserConvert.INSTANCE.convert(user, level,paidMemberUserDO.getPayMemberType(),paidMemberUserDO.getCardExpirationTime())); } @PutMapping("/update") diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java index e81b5bf..c7e1d3e 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java @@ -53,6 +53,15 @@ public class AppMemberUserInfoRespVO { @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) private LocalDateTime cardExpirationTime; + @Schema(description = "是否是客服") + private boolean idKefu=false; + + @Schema(description = "客服图片") + private String kefuPic; + + @Schema(description = "未读消息数量") + private Integer unreadCount=0; + @Schema(description = "用户 App - 会员等级") @Data public static class Level {