123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- <template>
- <div class="single-page h-full w-full" style="height: 100vh">
- <van-nav-bar @click-left="router.back()" @click-right="onClickRight">
- <template #left>
- <div>
- <van-icon name="arrow-left" color="black" size="18"/>
- </div>
- </template>
- <template #title>
- <div class="text-2xl text-black-3 text-semibold">
- <div class="inline-block w-220 line-clamp-1">
- {{ title }}
- </div>
- <!-- <span class="ml-7 iconfont icon-close-remind text-black-9" style="font-size: 16px"></span> -->
- </div>
- </template>
- <template #right>
- <van-icon name="ellipsis" color="black" size="18"/>
- </template>
- </van-nav-bar>
- <template v-if="showPage">
- <van-list
- ref="chatListRef"
- class="flex-1 overflow-y-auto px-12 flex flex-col"
- :finished="true"
- finished-text=""
- >
- <template v-for="(message, index) in currConversationChatList" :key="index">
- <ChatMessage :show-name="true" :message="message" ></ChatMessage>
- </template>
- </van-list>
- <!-- <van-pull-refresh v-model="refreshing" @refresh="loadMore" class="flex-1">
- </van-pull-refresh>-->
- <!-- <div class="fixed bottom-0 left-0 right-0 w-full">-->
- <ChatInput :operates="['image', 'share-group']" @focus="scrollToBottom" @send="handleSendMessage"></ChatInput>
- <!-- </div>-->
- </template>
- <template v-else>
- <div class="flex-1 grid place-items-center text-black-9">
- <div v-if="pageLoading">创建会话中...</div>
- <div v-else class="grid place-items-center">
- <div v-if="groupId">创建成功</div>
- <div v-else class="grid place-items-center">
- <div class="mb-10">创建会话失败</div>
- <van-button size="small" @click="initGroupId">点击重试</van-button>
- </div>
- </div>
- </div>
- </template>
- </div>
- </template>
- <script setup>
- import ChatMessage from './chat-message'
- import ChatInput from "./chat-input";
- import {findHyperlinks} from "~/pages/chat/chat-message/link-message/handle";
- import {XYWebSocket} from "~/utils/XYWebSocket";
- import {isValidJson} from "~/utils";
- const route = useRoute()
- const router = useRouter()
- const chatsStore = useChatsStore();
- const userInfoStore = useUserInfoStore();
- const {userInfo} = storeToRefs(userInfoStore);
- // 单聊的标题
- const title = computed(() => route.query.groupRemark)
- // 聊天列表
- const chatListRef = ref(null);
- const pageLoading = ref(true);
- const getUserId = ref(null); // 消息接收者的用户id
- const sendUserId = computed(() => userInfo?.value.pass) // 消息发送者:当前登录用户的加密id
- const groupId = ref(route.query?.groupId); // 会话ID
- const showPage = computed(() => groupId.value)
- const initGroupId = async () => {
- try {
- /* if (!groupId.value) return;
- pageLoading.value = true;
- const res = await chatsStore.getCurrConversationId(getUserId.value)
- await handleResponse(res)
- groupId.value = res.data;*/
- await getChatList('init')
- } catch (e) {
- } finally {
- pageLoading.value = false;
- }
- }
- let pageNum = ref(0)
- const currConversationChatList = ref([]);
- /**
- * 加载当前聊天信息
- * @param type init|more
- * @returns {Promise<void>}
- */
- const getChatList = async (type = 'init') => {
- try {
- const page = type === 'init' ? 1 : pageNum.value + 1;
- const res = await chatsStore.getChatHistory({
- pageNum: page,
- pageSize: 100,
- groupId: groupId.value,
- })
- pageNum.value = page;
- await handleResponse(res);
- currConversationChatList.value = handleChatList(res.data?.data)
- console.log(currConversationChatList.value, 'currConversationChatList')
- if (type === 'init') await scrollToBottom()
- } catch (e) {
- console.error(e)
- } finally {
- }
- }
- const handleChatList = (list = []) => {
- return (list ?? []).filter(o => isValidJson(o.messageContent)).map(o => JSON.parse(o.messageContent));
- }
- // 发送文本消息
- const sendTextMessage = async (text) => {
- try {
- console.log(text, 'sendTextMessage')
- if (!text) return
- let msg = {
- groupId: groupId.value,
- getUserId: getUserId.value,
- sendUserId: sendUserId.value,
- specialUserId: '',
- messageContent: text,
- messageType: 0,
- noticeType: 2,
- object: {
- id: getLocalId()
- }
- }
- const isLink = !!findHyperlinks(text)
- if (isLink) msg.messageType = 4;
- currConversationChatList.value.push(msg)
- await scrollToBottom()
- const res = await chatsStore.sendSocketMessage(msg)
- console.log('luck:', res)
- } catch (e) {
- console.log(e, '2')
- } finally {
- }
- }
- // 选择发送图片
- const sendImageMessage = async (file) => {
- try {
- const formData = new FormData()
- formData.append('uploadFile', file)
- formData.append('asImage', true)
- formData.append('fieldName', 'messageContent')
- const {data} = await request('/website/tourMessage/upload', {
- method: 'post',
- body: formData
- })
- let msg = {
- groupId: groupId.value,
- getUserId: getUserId.value,
- sendUserId: sendUserId.value,
- specialUserId: '',
- messageContent: data.fileUrl,
- messageType: 1,
- noticeType: 2,
- object: {
- id: getLocalId()
- }
- }
- currConversationChatList.value.push(msg)
- await scrollToBottom()
- await chatsStore.sendSocketMessage(msg)
- } catch (e) {
- console.error(e, '??')
- } finally {
- }
- }
- const handleSendMessage = async ({type, messageContent}) => {
- try {
- switch (type) {
- case 'text':
- await sendTextMessage(messageContent)
- break;
- case 'image':
- await sendImageMessage(messageContent)
- break;
- default:
- break;
- }
- } catch (e) {
- } finally {
- }
- }
- const scrollToBottom = async () => {
- setTimeout(async () => {
- await nextTick(); // 确保DOM已经更新
- const listElement = chatListRef.value?.$el;
- if (listElement) {
- const scrollContainer = listElement;
- scrollContainer.scrollTop = scrollContainer.scrollHeight;
- }
- }, 200)
- };
- // 加载更多
- const refreshing = ref(false)
- const loadMore = async () => {
- try {
- refreshing.value = true
- await getChatList('more')
- } catch (e) { } finally {
- refreshing.value = false
- }
- }
- const onClickRight = () => {
- groupId.value && navigateTo({
- path: '/chat/set',
- query: {groupId: groupId.value}
- })
- }
- // 本地生成一个唯一消息id
- function getLocalId() {
- const random = Math.floor(Math.random() * 10000)
- return Date.now() + '' + random
- }
- onMounted(() => {
- initGroupId()
- XYWebSocket.SocketEventsBus.on(XYWebSocket.SocketEvents.chatEvent, async (chat) => {
- const isCurrGroupId = chat.groupId && chat.groupId === groupId.value;
- const isOtherUserMessage = chat.sendUserId && chatsStore.isRealMessage(chat.sendUserId);
- if (isCurrGroupId && isOtherUserMessage) {
- currConversationChatList.value.push(chat)
- await scrollToBottom()
- }
- })
- })
- // 用户删除消息
- const delMessage = (messageId) => {
- showConfirmDialog({
- width: 260,
- message: '是否删除这条消息?',
- confirmButtonColor: '#FF9300'
- })
- .then(async () => {
- const res = await request('/website/tourMessage/delMessage', {
- method: 'post',
- body: {
- messageId: [messageId]
- }
- })
- if (res && res?.success) {
- }
- })
- .catch(() => {
- })
- }
- definePageMeta({
- layout: false
- })
- </script>
- <style lang="scss" scoped>
- .single-page {
- height: 100vh;
- display: flex;
- flex-direction: column;
- min-height: 0;
- }
- </style>
|