From 0e37da858413d99aae7eb459e7abd81d199b951c Mon Sep 17 00:00:00 2001
From: XinWei <2718030729@qq.com>
Date: Fri, 25 Oct 2024 11:23:22 +0800
Subject: [PATCH] =?UTF-8?q?=E5=90=8E=E5=8F=B0-=E5=AE=A2=E6=9C=8D=E9=A1=B5?=
=?UTF-8?q?=E9=9D=A2=E8=B0=83=E6=95=B4=E5=92=8C=E5=AE=A2=E6=9C=8D=E8=BD=AC?=
=?UTF-8?q?=E6=8E=A5=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../mall/promotion/kefu/conversation/index.ts | 11 ++-
.../api/mall/promotion/supportstaff/index.ts | 1 +
yudao-admin-vue3/src/utils/auth.ts | 11 +++
.../kefu/components/KeFuConversationList.vue | 8 +-
.../kefu/components/KeFuMessageList.vue | 72 +++++++++++++++---
.../kefu/components/asserts/zhuanjie.png | Bin 0 -> 8532 bytes
.../kefu/components/message/ProductItem.vue | 9 ++-
.../src/views/mall/promotion/kefu/index.vue | 10 +--
.../mall/promotion/supportstaff/index.vue | 4 +-
.../kefu/KeFuConversationController.java | 35 +++++++--
.../conversation/KeFuConversationRespVO.java | 3 +
.../dataobject/kefu/KeFuConversationDO.java | 5 ++
.../mysql/kefu/KeFuConversationMapper.java | 6 ++
.../service/kefu/KeFuConversationService.java | 23 +++++-
.../kefu/KeFuConversationServiceImpl.java | 18 +++++
15 files changed, 187 insertions(+), 29 deletions(-)
create mode 100644 yudao-admin-vue3/src/views/mall/promotion/kefu/components/asserts/zhuanjie.png
diff --git a/yudao-admin-vue3/src/api/mall/promotion/kefu/conversation/index.ts b/yudao-admin-vue3/src/api/mall/promotion/kefu/conversation/index.ts
index 2dbf331..6e9589c 100644
--- a/yudao-admin-vue3/src/api/mall/promotion/kefu/conversation/index.ts
+++ b/yudao-admin-vue3/src/api/mall/promotion/kefu/conversation/index.ts
@@ -1,4 +1,5 @@
import request from '@/config/axios'
+import { number } from 'vue-types'
export interface KeFuConversationRespVO {
id: number // 编号
@@ -21,6 +22,10 @@ export const KeFuConversationApi = {
getConversationList: async () => {
return await request.get({ url: '/promotion/kefu-conversation/list' })
},
+ // 获得客服会话列表
+ getConversationListByKefuId: async (kefuId: number) => {
+ return await request.get({ url: '/promotion/kefu-conversation/list?kefuId=' + kefuId })
+ },
// 客服会话置顶
updateConversationPinned: async (data: any) => {
return await request.put({
@@ -30,6 +35,10 @@ export const KeFuConversationApi = {
},
// 删除客服会话
deleteConversation: async (id: number) => {
- return await request.get({ url: '/promotion/kefu-conversation/delete?id' + id })
+ return await request.delete({ url: '/promotion/kefu-conversation/delete?id=' + id })
+ },
+ // 转接会话给其它客服
+ transferConversion: async (id: number, kefuId: number) => {
+ return await request.get({ url: `/promotion/kefu-conversation/transfer/${id}/${kefuId}`})
}
}
diff --git a/yudao-admin-vue3/src/api/mall/promotion/supportstaff/index.ts b/yudao-admin-vue3/src/api/mall/promotion/supportstaff/index.ts
index b8e7424..99dce9c 100644
--- a/yudao-admin-vue3/src/api/mall/promotion/supportstaff/index.ts
+++ b/yudao-admin-vue3/src/api/mall/promotion/supportstaff/index.ts
@@ -25,6 +25,7 @@ export const SupportStaffApi = {
return await request.get({ url: `/promotion/support-staff/get?id=` + id })
},
+
// 新增客服人员
createSupportStaff: async (data: SupportStaffVO) => {
return await request.post({ url: `/promotion/support-staff/create`, data })
diff --git a/yudao-admin-vue3/src/utils/auth.ts b/yudao-admin-vue3/src/utils/auth.ts
index c68a67a..18f48ff 100644
--- a/yudao-admin-vue3/src/utils/auth.ts
+++ b/yudao-admin-vue3/src/utils/auth.ts
@@ -6,6 +6,7 @@ const { wsCache } = useCache()
const AccessTokenKey = 'ACCESS_TOKEN'
const RefreshTokenKey = 'REFRESH_TOKEN'
+const StaffTokenKey = 'STAFF_TOKEN'
// 获取token
export const getAccessToken = () => {
@@ -30,6 +31,16 @@ export const removeToken = () => {
wsCache.delete(RefreshTokenKey)
}
+// 获取客服id TODO:后面可以完善为token
+export const getStaffToken = () => {
+ // 此处与TokenKey相同,此写法解决初始化时Cookies中不存在TokenKey报错
+ return wsCache.get(StaffTokenKey) ? wsCache.get(StaffTokenKey) : wsCache.get('STAFF_TOKEN')
+}
+// 设置客服id TODO:后面可以完善为token
+export const setStaffToken = (id: number) => {
+ wsCache.set(StaffTokenKey, id)
+}
+
/** 格式化token(jwt格式) */
export const formatToken = (token: string): string => {
return 'Bearer ' + token
diff --git a/yudao-admin-vue3/src/views/mall/promotion/kefu/components/KeFuConversationList.vue b/yudao-admin-vue3/src/views/mall/promotion/kefu/components/KeFuConversationList.vue
index 6e01123..079c415 100644
--- a/yudao-admin-vue3/src/views/mall/promotion/kefu/components/KeFuConversationList.vue
+++ b/yudao-admin-vue3/src/views/mall/promotion/kefu/components/KeFuConversationList.vue
@@ -74,6 +74,7 @@ import { useEmoji } from './tools/emoji'
import { formatPast } from '@/utils/formatTime'
import { KeFuMessageContentTypeEnum } from './tools/constants'
import { useAppStore } from '@/store/modules/app'
+import { getStaffToken} from '@/utils/auth'
defineOptions({ name: 'KeFuConversationList' })
@@ -86,7 +87,7 @@ const collapse = computed(() => appStore.getCollapse) // 折叠菜单
/** 加载会话列表 */
const getConversationList = async () => {
- const list = await KeFuConversationApi.getConversationList()
+ const list = await KeFuConversationApi.getConversationListByKefuId(getStaffToken())
list.sort((a: KeFuConversationRespVO, _) => (a.adminPinned ? -1 : 1))
conversationList.value = list
}
@@ -206,8 +207,9 @@ watch(showRightMenu, (val) => {
}
.active {
- border-left: 5px #3271ff solid;
- background-color: var(--login-bg-color);
+ border-left: 5px #0256ff solid;
+ // background-color: var(--login-bg-color);
+ background-color: #409eff;
}
.pinned {
diff --git a/yudao-admin-vue3/src/views/mall/promotion/kefu/components/KeFuMessageList.vue b/yudao-admin-vue3/src/views/mall/promotion/kefu/components/KeFuMessageList.vue
index 0a59b0f..7d22683 100644
--- a/yudao-admin-vue3/src/views/mall/promotion/kefu/components/KeFuMessageList.vue
+++ b/yudao-admin-vue3/src/views/mall/promotion/kefu/components/KeFuMessageList.vue
@@ -10,7 +10,8 @@
-
{{ formatDate(item.createTime) }}
@@ -20,16 +21,19 @@
{{ item.content }}
-
-
-
@@ -40,13 +44,15 @@
-
-
-
-
-
有新消息
@@ -81,6 +90,19 @@
+
+
+
+
+
+
+
+ {{ staff.name }}
+
+
+
+
+
@@ -119,6 +141,7 @@
import PictureSelectUpload from './tools/PictureSelectUpload.vue'
// import VerbalTrick from './tools/VerbalTrick.vue'
import Picture from '@/views/mall/promotion/kefu/components/asserts/huashu.png'
+ import Picture2 from '@/views/mall/promotion/kefu/components/asserts/zhuanjie.png'
import ProductItem from './message/ProductItem.vue'
import OrderItem from './message/OrderItem.vue'
import { Emoji, useEmoji } from './tools/emoji'
@@ -130,6 +153,9 @@
import relativeTime from 'dayjs/plugin/relativeTime'
import { debounce } from 'lodash-es'
import { jsonParse } from '@/utils'
+ import { getStaffToken, setStaffToken} from '@/utils/auth'
+ import type { DropdownInstance } from 'element-plus'
+ import { ref } from 'vue'
dayjs.extend(relativeTime)
@@ -145,6 +171,10 @@
const messageList = ref
([]) // 消息列表
const conversation = ref({} as KeFuConversationRespVO) // 用户会话
const showNewMessageTip = ref(false) // 显示有新消息提示
+ import { SupportStaffApi, SupportStaffVO } from '@/api/mall/promotion/supportstaff' // 客服列表接口
+ import { KeFuConversationApi} from '@/api/mall/promotion/kefu/conversation'
+ import { number } from 'vue-types'
+ const onlineStaffList = ref([]) // 在线客服列表的数据
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
@@ -152,6 +182,7 @@
})
const total = ref(0) // 消息总条数
const refreshContent = ref(false) // 内容刷新,主要解决会话消息页面高度不一致导致的滚动功能精度失效
+ const dropdown1 = ref()
/** 获悉消息内容 */
const getMessageContent = computed(() => (item : any) => jsonParse(item.content))
@@ -360,8 +391,29 @@
}
return false
})
+ /** 查询在线客服人员列表 */
+ const getOnlineStaffList = async () => {
+ if (!dropdown1.value) return
+ dropdown1.value.handleOpen()
+ try {
+ const data = await SupportStaffApi.getSupportStaffPage({
+ pageNo: 1,
+ pageSize: 10,
+ status: 1,
+ })
+ onlineStaffList.value = data.list
+ } finally {
+ }
+ }
-
+ /** 转接客服人员列表 id:会话id kefuId:客服人员id */
+ const transferConversion = async (kefuId: number) => {
+ try {
+ await KeFuConversationApi.transferConversion(queryParams.conversationId, kefuId)
+ } finally {
+ // todo 刷新会话列表
+ }
+ }
/** 初始化 **/
onMounted(() => {
getVerbalTrickList()
diff --git a/yudao-admin-vue3/src/views/mall/promotion/kefu/components/asserts/zhuanjie.png b/yudao-admin-vue3/src/views/mall/promotion/kefu/components/asserts/zhuanjie.png
new file mode 100644
index 0000000000000000000000000000000000000000..97e866ab3611dea13f1a2121534b684374c79fbe
GIT binary patch
literal 8532
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 {
}
.title-text {
- font-size: 13px;
+ font-size: 12px;
font-weight: 500;
line-height: 20px;
+ display: -webkit-box; /* 对于支持的浏览器 */
+ -webkit-box-orient: vertical; /* 垂直排列 */
+ overflow: hidden; /* 隐藏超出部分 */
+ -webkit-line-clamp: 2; /* 限制为2行 */
+ text-overflow: ellipsis; /* 超出部分显示省略号 */
+ line-height: 1.5; /* 行高,可以根据需要调整 */
+ max-height: 3rem; /* 根据行高和行数设置最大高度,2行 * 行高 */
}
.spec-text {
diff --git a/yudao-admin-vue3/src/views/mall/promotion/kefu/index.vue b/yudao-admin-vue3/src/views/mall/promotion/kefu/index.vue
index 554d710..bf94e40 100644
--- a/yudao-admin-vue3/src/views/mall/promotion/kefu/index.vue
+++ b/yudao-admin-vue3/src/views/mall/promotion/kefu/index.vue
@@ -1,19 +1,19 @@
-
+
-
+
-
+
-
+
@@ -42,7 +42,7 @@
/** 发起 WebSocket 连接 */
const { data, close, open } = useWebSocket(server.value, {
- autoReconnect: true,
+ autoReconnect: false,
heartbeat: true
})
diff --git a/yudao-admin-vue3/src/views/mall/promotion/supportstaff/index.vue b/yudao-admin-vue3/src/views/mall/promotion/supportstaff/index.vue
index 7a82a33..ca1bf85 100644
--- a/yudao-admin-vue3/src/views/mall/promotion/supportstaff/index.vue
+++ b/yudao-admin-vue3/src/views/mall/promotion/supportstaff/index.vue
@@ -214,7 +214,7 @@ import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { SupportStaffApi, SupportStaffVO } from '@/api/mall/promotion/supportstaff'
import SupportStaffForm from './SupportStaffForm.vue'
-
+import { setStaffToken} from '@/utils/auth'
/** 客服人员 列表 */
defineOptions({ name: 'SupportStaff' })
@@ -285,8 +285,8 @@ const handleDelete = async (id: number) => {
}
/** 客服进入工作台 */
const handleEnterConsole = async (id: number) => {
+ setStaffToken(id);
window.open(`${window.location.origin}/kefu/kefu`, '_blank');
-
}
/** 导出按钮操作 */
const handleExport = async () => {
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/KeFuConversationController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/KeFuConversationController.java
index 2190a66..74ca43f 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/KeFuConversationController.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/KeFuConversationController.java
@@ -6,6 +6,7 @@ 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.conversation.KeFuConversationUpdatePinnedReqVO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuConversationDO;
import cn.iocoder.yudao.module.promotion.service.kefu.KeFuConversationService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -16,6 +17,7 @@ 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;
@@ -54,16 +56,37 @@ public class KeFuConversationController {
@GetMapping("/list")
@Operation(summary = "获得客服会话列表")
@PreAuthorize("@ss.hasPermission('promotion:kefu-conversation:query')")
- public CommonResult> getConversationList() {
- // 查询会话列表
- List respList = BeanUtils.toBean(conversationService.getKefuConversationList(),
- KeFuConversationRespVO.class);
+ public CommonResult> getConversationList(@RequestParam(required = false, value = "kefuId") Long kefuId) {
+ // 如果会话列表中的kefuId为null,则转接给当前kefuId(处理小程序新会话)
+ if (kefuId != null) {
+ List updateList = new ArrayList<>();
+ List allConversationList = BeanUtils.toBean(conversationService.getKefuConversationList(),
+ KeFuConversationRespVO.class);
+ for (KeFuConversationRespVO keFuConversationRespVO : allConversationList) {
+ if (keFuConversationRespVO.getKefuId() == null) {
+ keFuConversationRespVO.setKefuId(kefuId);
+ updateList.add(BeanUtils.toBean(keFuConversationRespVO, KeFuConversationDO.class));
+ }
+ }
+ if (!updateList.isEmpty()) {
+ conversationService.updateConversation(updateList);
+ }
+ }
+ // 查询会话列表
+ List respList = BeanUtils.toBean(conversationService.getKefuConversationList(kefuId),
+ 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())));
+ respList.forEach(item -> findAndThen(userMap, item.getUserId(),
+ memberUser -> item.setUserAvatar(memberUser.getAvatar()).setUserNickname(memberUser.getNickname())));
return success(respList);
}
+ @GetMapping("/transfer/{id}/{kefuId}")
+ public CommonResult getSupportStaff(@PathVariable("id") Long id, @PathVariable("kefuId") Long kefuId) {
+ conversationService.transferConversation(id, kefuId);
+ // 处理逻辑
+ return success(true);
+ }
}
\ 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/kefu/vo/conversation/KeFuConversationRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/conversation/KeFuConversationRespVO.java
index 98cd5ac..0a9a624 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/conversation/KeFuConversationRespVO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/conversation/KeFuConversationRespVO.java
@@ -43,4 +43,7 @@ public class KeFuConversationRespVO {
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
+ @Schema(description = "所属客服编号")
+ private Long kefuId;
+
}
\ No newline at end of file
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KeFuConversationDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KeFuConversationDO.java
index 482b6cd..ad4fbc5 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KeFuConversationDO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KeFuConversationDO.java
@@ -80,4 +80,9 @@ public class KeFuConversationDO extends BaseDO {
*/
private Integer adminUnreadMessageCount;
+ /**
+ * 所属客服编号
+ */
+ private Long kefuId;
+
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/kefu/KeFuConversationMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/kefu/KeFuConversationMapper.java
index 40efa44..6178cb2 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/kefu/KeFuConversationMapper.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/kefu/KeFuConversationMapper.java
@@ -21,6 +21,12 @@ public interface KeFuConversationMapper extends BaseMapperX
.eq(KeFuConversationDO::getAdminDeleted, Boolean.FALSE)
.orderByDesc(KeFuConversationDO::getCreateTime));
}
+ default List selectConversationList(Long kefuId) {
+ return selectList(new LambdaQueryWrapperX()
+ .eq(KeFuConversationDO::getAdminDeleted, Boolean.FALSE)
+ .eqIfPresent(KeFuConversationDO::getKefuId, kefuId)
+ .orderByDesc(KeFuConversationDO::getCreateTime));
+ }
default void updateAdminUnreadMessageCountIncrement(Long id) {
update(new LambdaUpdateWrapper()
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuConversationService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuConversationService.java
index 2da8d0b..9fd313d 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuConversationService.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuConversationService.java
@@ -50,11 +50,18 @@ public interface KeFuConversationService {
void updateConversationAdminDeleted(Long id, Boolean adminDeleted);
/**
- * 【管理员】获得客服会话列表
+ * 【管理员】获得全部客服会话列表
*
* @return 会话列表
*/
List getKefuConversationList();
+ /**
+ * 【管理员】获得客服会话列表
+ *
+ * @param kefuId 客服编号
+ * @return 会话列表
+ */
+ List getKefuConversationList(Long kefuId);
/**
* 【会员】获得或创建会话
@@ -82,4 +89,18 @@ public interface KeFuConversationService {
*/
KeFuConversationDO getConversationByUserId(Long userId);
+ /**
+ * 更新客服列表
+ * @param updateList
+ * @return void
+ */
+ void updateConversation(List updateList);
+
+ /**
+ * 转接会话
+ * @param id 会话id
+ * @param kefuId 客服id
+ * @return void
+ */
+ void transferConversation(Long id, Long kefuId);
}
\ 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/KeFuConversationServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuConversationServiceImpl.java
index ee67a57..b53e08d 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
@@ -87,6 +87,11 @@ public class KeFuConversationServiceImpl implements KeFuConversationService {
return conversationMapper.selectConversationList();
}
+ @Override
+ public List getKefuConversationList(Long kefuId) {
+ return conversationMapper.selectConversationList(kefuId);
+ }
+
@Override
public KeFuConversationDO getOrCreateConversation(Long userId) {
KeFuConversationDO conversation = conversationMapper.selectOne(KeFuConversationDO::getUserId, userId);
@@ -115,4 +120,17 @@ public class KeFuConversationServiceImpl implements KeFuConversationService {
return conversationMapper.selectByUserId(userId);
}
+ @Override
+ public void updateConversation(List updateList) {
+ conversationMapper.updateBatch(updateList);
+ }
+
+ @Override
+ public void transferConversation(Long id, Long kefuId) {
+ KeFuConversationDO keFuConversationDO = new KeFuConversationDO();
+ keFuConversationDO.setId(id);
+ keFuConversationDO.setKefuId(kefuId);
+ conversationMapper.updateById(keFuConversationDO);
+ }
+
}
\ No newline at end of file