feat: [mall] kefu 客服模块迁移 代码风格统一

pull/243/head
jawe 2025-10-30 16:27:44 +08:00
parent 0ef91c1cad
commit f331f46ff9
8 changed files with 79 additions and 76 deletions

View File

@ -27,24 +27,24 @@ const collapse = ref(false); // 折叠菜单
/** 计算消息最后发送时间距离现在过去了多久 */
const lastMessageTimeMap = ref<Map<number, string>>(new Map<number, string>());
const calculationLastMessageTime = () => {
function calculationLastMessageTime() {
kefuStore.getConversationList?.forEach((item) => {
lastMessageTimeMap.value.set(
item.id,
formatPast(item.lastMessageTime, 'YYYY-MM-DD'),
);
});
};
}
defineExpose({ calculationLastMessageTime });
const openRightMessage = (item: MallKefuConversationApi.Conversation) => {
function openRightMessage(item: MallKefuConversationApi.Conversation) {
//
if (activeConversationId.value === item.id) {
return;
}
activeConversationId.value = item.id;
emits('change', item);
};
}
/** 获得消息类型 */
const getConversationDisplayText = computed(
@ -88,10 +88,10 @@ const rightClickConversation = ref<MallKefuConversationApi.Conversation>(
); //
/** 打开右键菜单 */
const rightClick = (
function rightClick(
mouseEvent: PointerEvent,
item: MallKefuConversationApi.Conversation,
) => {
) {
rightClickConversation.value = item;
//
showRightMenu.value = true;
@ -101,14 +101,14 @@ const rightClick = (
? `${mouseEvent.clientX - 80}px`
: `${mouseEvent.clientX - 210}px`,
};
};
}
/** 关闭右键菜单 */
const closeRightMenu = () => {
function closeRightMenu() {
showRightMenu.value = false;
};
}
/** 置顶会话 */
const updateConversationPinned = async (adminPinned: boolean) => {
async function updateConversationPinned(adminPinned: boolean) {
// 1. /
await KeFuConversationApi.updateConversationPinned({
id: rightClickConversation.value.id,
@ -118,17 +118,17 @@ const updateConversationPinned = async (adminPinned: boolean) => {
// 2.
closeRightMenu();
await kefuStore.updateConversation(rightClickConversation.value.id);
};
}
/** 删除会话 */
const deleteConversation = async () => {
async function deleteConversation() {
// 1.
await message.confirm('您确定要删除该会话吗?');
await KeFuConversationApi.deleteConversation(rightClickConversation.value.id);
// 2.
closeRightMenu();
kefuStore.deleteConversation(rightClickConversation.value.id);
};
}
/** 监听右键菜单的显示状态,添加点击事件监听器 */
watch(showRightMenu, (val) => {

View File

@ -53,7 +53,7 @@ const getMessageContent = computed(
() => (item: any) => jsonParse(item.content),
);
/** 获得消息列表 */
const getMessageList = async () => {
async function getMessageList() {
const res = await KeFuMessageApi.getKeFuMessageList(queryParams);
if (isEmpty(res)) {
//
@ -72,15 +72,15 @@ const getMessageList = async () => {
messageList.value = res;
}
refreshContent.value = true;
};
}
/** 添加消息 */
const pushMessage = (message: any) => {
function pushMessage(message: any) {
if (messageList.value.some((val) => val.id === message.id)) {
return;
}
messageList.value.push(message);
};
}
/** 按照时间倒序,获取消息列表 */
const getMessageList0 = computed(() => {
@ -91,7 +91,7 @@ const getMessageList0 = computed(() => {
});
/** 刷新消息列表 */
const refreshMessageList = async (message?: any) => {
async function refreshMessageList(message?: any) {
if (!conversation.value) {
return;
}
@ -114,10 +114,10 @@ const refreshMessageList = async (message?: any) => {
//
await handleToNewMessage();
}
};
}
/** 获得新会话的消息列表, 点击切换时读取缓存然后异步获取新消息merge 下; */
const getNewMessageList = async (val: MallKefuMessageApi.Message) => {
async function getNewMessageList(val: MallKefuMessageApi.Message) {
// 1.
kefuStore.saveMessageList(conversation.value.id, messageList.value);
// 2.1 ,
@ -132,19 +132,23 @@ const getNewMessageList = async (val: MallKefuMessageApi.Message) => {
queryParams.createTime = undefined;
// 3.
await refreshMessageList();
};
}
defineExpose({ getNewMessageList, refreshMessageList });
const showKeFuMessageList = computed(() => !isEmpty(conversation.value)); //
//
function showKeFuMessageList() {
return !isEmpty(conversation.value);
}
const skipGetMessageList = ref(false); //
/** 处理表情选择 */
const handleEmojiSelect = (item: Emoji) => {
function handleEmojiSelect(item: Emoji) {
message.value += item.name;
};
}
/** 处理图片发送 */
const handleSendPicture = async (picUrl: string) => {
async function handleSendPicture(picUrl: string) {
//
const msg = {
conversationId: conversation.value.id,
@ -152,10 +156,10 @@ const handleSendPicture = async (picUrl: string) => {
content: JSON.stringify({ picUrl }),
};
await sendMessage(msg);
};
}
/** 发送文本消息 */
const handleSendMessage = async (event: any) => {
async function handleSendMessage(event: any) {
// shift
if (event.shiftKey) {
return;
@ -173,10 +177,10 @@ const handleSendMessage = async (event: any) => {
content: JSON.stringify({ text: message.value }),
};
await sendMessage(msg);
};
}
/** 真正发送消息 【共用】*/
const sendMessage = async (msg: MallKefuMessageApi.MessageSend) => {
async function sendMessage(msg: MallKefuMessageApi.MessageSend) {
//
await KeFuMessageApi.sendKeFuMessage(msg);
message.value = '';
@ -184,14 +188,14 @@ const sendMessage = async (msg: MallKefuMessageApi.MessageSend) => {
await refreshMessageList();
//
await kefuStore.updateConversation(conversation.value.id);
};
}
/** 滚动到底部 */
const innerRef = ref<HTMLDivElement>();
const scrollbarRef = ref<HTMLElement | null>(null);
const { y } = useScroll(scrollbarRef);
const scrollToBottom = async () => {
async function scrollToBottom() {
if (!scrollbarRef.value) return;
// 1.
if (loadHistory.value) {
@ -206,13 +210,13 @@ const scrollToBottom = async () => {
showNewMessageTip.value = false;
// 2.2
await KeFuMessageApi.updateKeFuMessageReadStatus(conversation.value.id);
};
}
/** 查看新消息 */
const handleToNewMessage = async () => {
async function handleToNewMessage() {
loadHistory.value = false;
await scrollToBottom();
};
}
const loadHistory = ref(false); //
/** 处理消息列表滚动事件(debounce 限流) */
@ -233,7 +237,7 @@ const handleScroll = useDebounceFn((state: UseScrollReturn) => {
}
}, 200);
/** 加载历史消息 */
const handleOldMessage = async () => {
async function handleOldMessage() {
//
const oldPageHeight = innerRef.value?.clientHeight;
if (!oldPageHeight) {
@ -247,7 +251,7 @@ const handleOldMessage = async () => {
scrollbarRef.value.scrollHeight -
innerRef.value!.clientHeight -
oldPageHeight;
};
}
/**
* 是否显示时间
@ -255,17 +259,15 @@ const handleOldMessage = async () => {
* @param {*} item - 数据
* @param {*} index - 索引
*/
const showTime = computed(
() => (item: MallKefuMessageApi.Message, index: number) => {
if (unref(messageList.value)[index + 1]) {
const dateString = dayjs(
unref(messageList.value)[index + 1].createTime,
).fromNow();
return dateString !== dayjs(unref(item).createTime).fromNow();
}
return false;
},
);
function showTime(item: MallKefuMessageApi.Message, index: number) {
if (unref(messageList.value)[index + 1]) {
const dateString = dayjs(
unref(messageList.value)[index + 1].createTime,
).fromNow();
return dateString !== dayjs(unref(item).createTime).fromNow();
}
return false;
}
</script>
<template>
@ -417,7 +419,7 @@ const showTime = computed(
</a-layout>
<a-layout v-else class="kefu">
<a-layout-content>
<Empty description="请选择左侧的一个会话后开始" class="mt-[50px]"/>
<Empty description="请选择左侧的一个会话后开始" class="mt-[50px]" />
</a-layout-content>
</a-layout>
</template>

View File

@ -8,7 +8,7 @@ import { isEmpty } from '@vben/utils';
// import { debounce } from 'lodash-es'
import { useDebounceFn } from '@vueuse/core';
import { Card, Empty,message } from 'ant-design-vue';
import { Card, Empty, message } from 'ant-design-vue';
import * as UserApi from '#/api/member/user';
import * as WalletApi from '#/api/pay/wallet/balance';
@ -29,14 +29,14 @@ const productBrowsingHistoryRef =
ref<InstanceType<typeof ProductBrowsingHistory>>();
const orderBrowsingHistoryRef =
ref<InstanceType<typeof OrderBrowsingHistory>>();
const handleClick = async (tab: string) => {
async function handleClick(tab: string) {
activeTab.value = tab;
await nextTick();
await getHistoryList();
};
}
/** 获得历史数据 */
const getHistoryList = async () => {
async function getHistoryList() {
switch (activeTab.value) {
case '交易订单': {
await orderBrowsingHistoryRef.value?.getHistoryList(conversation.value);
@ -55,10 +55,10 @@ const getHistoryList = async () => {
break;
}
}
};
}
/** 加载下一页数据 */
const loadMore = async () => {
async function loadMore() {
switch (activeTab.value) {
case '交易订单': {
await orderBrowsingHistoryRef.value?.loadMore();
@ -75,18 +75,18 @@ const loadMore = async () => {
break;
}
}
};
}
/** 浏览历史初始化 */
const conversation = ref<MallKefuConversationApi.Conversation>(
{} as MallKefuConversationApi.Conversation,
); //
const initHistory = async (val: MallKefuConversationApi.Conversation) => {
async function initHistory(val: MallKefuConversationApi.Conversation) {
activeTab.value = '会员信息';
conversation.value = val;
await nextTick();
await getHistoryList();
};
}
defineExpose({ initHistory });
/** 处理消息列表滚动事件(debounce 限流) */
@ -106,7 +106,8 @@ const WALLET_INIT_DATA = {
totalRecharge: 0,
} as WalletApi.WalletVO; //
const wallet = ref<WalletApi.WalletVO>(WALLET_INIT_DATA); //
const getUserWallet = async () => {
async function getUserWallet() {
if (!conversation.value.userId) {
wallet.value = WALLET_INIT_DATA;
return;
@ -114,12 +115,12 @@ const getUserWallet = async () => {
wallet.value =
(await WalletApi.getWallet({ userId: conversation.value.userId })) ||
WALLET_INIT_DATA;
};
}
/** 获得用户 */
const loading = ref(true); //
const user = ref<UserApi.UserVO>({} as UserApi.UserVO);
const getUserData = async () => {
async function getUserData() {
loading.value = true;
try {
const res = await UserApi.getUser(conversation.value.userId);
@ -132,7 +133,7 @@ const getUserData = async () => {
} finally {
loading.value = false;
}
};
}
</script>
<template>

View File

@ -24,15 +24,15 @@ const skipGetMessageList = computed(() => {
}); //
/** 获得浏览记录 */
const getHistoryList = async (val: MallKefuConversationApi.Conversation) => {
async function getHistoryList(val: MallKefuConversationApi.Conversation) {
queryParams.userId = val.userId;
const res = await getOrderPage(queryParams);
total.value = res.total;
list.value = res.list;
};
}
/** 加载下一页数据 */
const loadMore = async () => {
async function loadMore() {
if (skipGetMessageList.value) {
return;
}
@ -41,7 +41,7 @@ const loadMore = async () => {
total.value = res.total;
// 使 concat
list.value = [...list.value, ...res.list];
};
}
defineExpose({ getHistoryList, loadMore });
</script>

View File

@ -26,15 +26,15 @@ const skipGetMessageList = computed(() => {
}); //
/** 获得浏览记录 */
const getHistoryList = async (val: MallKefuConversationApi.Conversation) => {
async function getHistoryList(val: MallKefuConversationApi.Conversation) {
queryParams.userId = val.userId;
const res = await getBrowseHistoryPage(queryParams);
total.value = res.total;
list.value = res.list;
};
}
/** 加载下一页数据 */
const loadMore = async () => {
async function loadMore() {
if (skipGetMessageList.value) {
return;
}
@ -43,7 +43,7 @@ const loadMore = async () => {
total.value = res.total;
// 使 concat
list.value = [...list.value, ...res.list];
};
}
defineExpose({ getHistoryList, loadMore });
</script>

View File

@ -24,9 +24,9 @@ const getMessageContent = computed(() =>
);
/** 查看订单详情 */
const openDetail = (id: number) => {
function openDetail(id: number) {
push({ name: 'TradeOrderDetail', params: { id } });
};
}
/**
* 格式化订单状态的颜色

View File

@ -37,9 +37,9 @@ defineProps({
const { push } = useRouter();
/** 查看商品详情 */
const openDetail = (spuId: number) => {
function openDetail(spuId: number) {
push({ name: 'ProductSpuDetail', params: { id: spuId } });
};
}
</script>
<template>
@ -89,10 +89,10 @@ const openDetail = (spuId: number) => {
align-items: center;
width: 100%;
padding: 10px;
margin-bottom: 10px;
background-color: rgb(128 128 128 / 30%);
border: 1px solid var(--el-border-color);
border-radius: 8px;
margin-bottom: 10px;
&-left {
width: 70px;

View File

@ -19,10 +19,10 @@ const emits = defineEmits<{
const { getEmojiList } = useEmoji();
const emojiList = computed(() => getEmojiList());
const handleSelect = (item: Emoji) => {
function handleSelect(item: Emoji) {
// emoji 便
emits('selectEmoji', item);
};
}
</script>
<template>