Files
cashier_wx/pageChat/index.vue
2025-12-05 19:19:54 +08:00

304 lines
7.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="min-page bg-f7 color-333 u-font-28">
<up-sticky>
<view class="top u-flex u-row-between u-col-center">
<view style="width: 420rpx">
<up-search
v-model="query.key"
placeholder="搜索群名称"
:showAction="false"
@clear="throttleSearch"
@change="throttleSearch"
></up-search>
</view>
<view class="u-flex u-col-center" @click="clearAllmsg">
<text class="color-666 u-m-r-12">清空未读</text>
<image src="/pageChat/static/clear.png" class="clear"></image>
</view>
</view>
</up-sticky>
<view class="list">
<up-swipe-action>
<template v-for="(item, index) in list" :key="item.id">
<up-swipe-action-item
:options="options1"
v-model:show="item.showOptions"
@click="optionsClick($event, item, index)"
>
<view class="item u-flex" @click="toDetail(item)">
<view class="u-flex avatar">
<up-avatar
size="118rpx"
:src="item.avatar"
shape="square"
round="8rpx"
></up-avatar>
<view class="bandage" v-if="item.unread_count > 0">{{
item.unread_count >= 99 ? "99" : item.unread_count
}}</view>
</view>
<view class="u-flex-1 u-flex u-row-between u-p-l-14">
<view style="max-width: 364rpx">
<view class="color-000 u-line-1">{{ item.name }}</view>
<view class="u-m-t-28 u-line-1 u-font-24 color-999">{{
item.msg
}}</view>
</view>
<view class="color-333 u-font-24">{{ item.send_time }}</view>
</view>
</view>
</up-swipe-action-item>
<view style="height: 16rpx" class="bg-f7"></view>
</template>
</up-swipe-action>
</view>
</view>
</template>
<script setup>
import * as chatApi from "@/http/php/chat";
import { ref, reactive, onMounted, onUnmounted } from "vue";
import { onShow } from "@dcloudio/uni-app";
import { useChatStore } from "@/stores/chat";
import dayjs from "dayjs";
const chatStore = useChatStore();
const originalOnReceiveMsg = chatStore.onReceiveMsg;
// 定义消息回调函数
const handleReceiveMsg = (msg) => {
// 先执行原始回调(如果有)
if (typeof originalOnReceiveMsg === "function") {
originalOnReceiveMsg(msg);
}
if (msg.operate_type == "receive_msg" && msg.chat_type == 2) {
const index = allList.value.findIndex((v) => v.group_id == msg.group_id);
if (index != -1) {
allList.value[index].unread_count += 1;
allList.value[index].msg = returnMsg(msg);
allList.value[index].send_time = msg.send_time;
allList.value[index].send_time_origin = msg.send_time_origin;
allList.value = listSort(allList.value);
}
const index1 = list.value.findIndex((v) => v.group_id == msg.group_id);
if (index1 != -1) {
list.value[index1].unread_count += 1;
list.value[index1].msg = returnMsg(msg);
list.value[index1].send_time = msg.send_time;
list.value[index1].send_time_origin = msg.send_time_origin;
list.value = listSort(list.value);
}
}
};
onMounted(() => {
chatStore.registerReceiveMsgCallback(handleReceiveMsg);
});
onUnmounted(() => {
// 移除消息回调,避免内存泄漏
chatStore.removeReceiveMsgCallback(handleReceiveMsg);
});
function returnMsg(msg) {
if (msg.msg_type == 1) {
return msg.nick + "" + msg.content;
}
if (msg.msg_type == 2) {
return msg.nick + "" + "[图片]";
}
if (msg.msg_type == 5) {
return msg.nick + "" + "[视频]";
}
if (msg.msg_type == 4) {
return msg.nick + "" + "[优惠券]";
}
}
chatStore.connectSocket();
// 使用 reactive 创建响应式对象
const options1 = reactive([
{
text: "删除",
style: {
backgroundColor: "#f56c6c",
color: "#fff",
},
},
]);
function optionsClick(e, item, index) {
if (e.index == 0) {
//删除
chatApi
.sessionlistdel({
session_id: item.session_id,
})
.then((res) => {
if (res) {
uni.showToast({
title: "删除成功",
icon: "none",
duration: 1000,
});
list.value.splice(index, 1);
setTimeout(() => {
getList();
}, 1000);
}
});
}
}
const list = ref([]);
let allList = ref([]);
const query = reactive({
key: "",
});
function throttle(fn, delay) {
let timer = null;
return function (...args) {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}
//使用节流函数
const throttleSearch = throttle(search, 500);
function search() {
const arr = allList.value
.filter((v) => v.name.includes(query.key.trim()))
.map((v) => {
return {
...v,
showOptions: false,
};
});
list.value = listSort(arr);
}
function listSort(arr) {
return arr.sort((a, b) => {
return dayjs(b.send_time_origin).unix() - dayjs(a.send_time_origin).unix();
});
}
async function getList() {
const res = await chatApi.messageSessionList({});
const arr = (res.list || []).filter((v) => !v.is_del);
allList.value = listSort(arr);
search();
}
async function clearAllmsg() {
uni.showModal({
title: "提示",
content: "确定要清空所有未读消息吗?",
success: async (res) => {
if (res.confirm) {
const res = await chatApi.messageMarkReadAll({
session_ids: list.value.map((v) => v.group_id).join(","),
});
if (res) {
uni.showToast({
title: "清空成功",
icon: "none",
duration: 2000,
});
setTimeout(() => {
getList();
}, 1000);
}
}
},
});
}
function toDetail(item) {
if (!item.is_th) {
return uni.showToast({
title: "你已不在该群内",
icon: "none",
duration: 1500,
});
}
uni.navigateTo({
url:
"/pageChat/chat" +
`?group_id=${item.group_id}&session_id=${item.session_id}`,
});
}
const messageUnreadCount = ref(0);
onShow(() => {
getList();
// 检查连接状态,确保连接活跃
if (!chatStore.isConnect || !chatStore.socketTask) {
console.log("列表页显示检查Socket连接");
chatStore.forceReconnect();
} else {
chatStore.shop_id = "";
chatStore.init();
}
// 获取未读消息总数
chatApi.messageUnreadCount({}).then((res) => {
console.log(res);
messageUnreadCount.value = res.total;
});
});
</script>
<style lang="scss" scoped>
.top {
padding: 32rpx 28rpx;
background-color: #fff;
}
.clear {
width: 38rpx;
height: 38rpx;
}
.list {
padding: 36rpx 28rpx;
.item {
padding: 32rpx 28rpx;
background-color: #fff;
border-radius: 16rpx;
.avatar {
position: relative;
.bandage {
position: absolute;
flex-direction: column;
justify-content: center;
align-items: center;
border-radius: 50%;
background: #ff1c1c;
font-size: 24rpx;
color: #ffffff;
width: 38rpx;
height: 38rpx;
text-align: center;
line-height: 38rpx;
right: -10rpx;
top: -10rpx;
}
}
}
}
:deep(.u-swipe-action-item__content) {
background-color: transparent;
}
:deep(.u-swipe-action-item) {
border-radius: 16rpx;
}
</style>