|
@@ -1,8 +1,8 @@
|
|
|
<template>
|
|
|
- <div class="chat" v-if="store.state.isShowChat">
|
|
|
+ <div class="chat" :class="{phone: Config.isPhone}">
|
|
|
<div class="message-top">
|
|
|
- <van-icon name="arrow-left" size="22" color="#1989fa" class="close-icon"
|
|
|
- @click="store.commit('setIsShowRight', false)"/>
|
|
|
+ <van-icon name="arrow-left" size="22" color="#1989fa" class="close-icon" v-if="Config.isPhone"
|
|
|
+ @click="router.back()"/>
|
|
|
<div class="common-pic" @click="showInfo">{{ store.state.chatUserInfo.friendName.charAt(0) }}</div>
|
|
|
<div class="username" @click="showInfo">{{ friendName }}</div>
|
|
|
<van-popover class="chat-popover"
|
|
@@ -33,12 +33,13 @@
|
|
|
<template v-else>{{ store.state.chatUserInfo.friendName.charAt(0) }}</template>
|
|
|
</div>
|
|
|
<div class="warp">
|
|
|
- <!-- <div class="username">{{ item.fromUsername }}</div>-->
|
|
|
- <div class="message"
|
|
|
+ <!--<div class="username">{{ item.fromUsername }}</div>-->
|
|
|
+ <div class="message" :class="{bg: pop.isShow && messageIndex === index}"
|
|
|
+ v-html="messageFormat(item.content)"
|
|
|
@contextmenu="onContextmenu($event,index)"
|
|
|
@touchstart="onTouchstart($event,index)"
|
|
|
@touchend="onTouchend"
|
|
|
- v-html="messageFormat(item.content)"/>
|
|
|
+ />
|
|
|
<div class="time">{{ formatDateTime(item.createdAt) }}</div>
|
|
|
</div>
|
|
|
</li>
|
|
@@ -70,7 +71,17 @@
|
|
|
|
|
|
<script lang="ts">
|
|
|
import V3Emoji from '../../../../components/V3Emoji.vue'
|
|
|
-import {computed, defineComponent, reactive, ref, toRefs, watch, nextTick, onUnmounted} from "vue";
|
|
|
+import {
|
|
|
+ computed,
|
|
|
+ defineComponent,
|
|
|
+ reactive,
|
|
|
+ ref,
|
|
|
+ toRefs,
|
|
|
+ watch,
|
|
|
+ nextTick,
|
|
|
+ onUnmounted,
|
|
|
+ onActivated, onMounted
|
|
|
+} from "vue";
|
|
|
import Client from "../../../../utils/client";
|
|
|
import {
|
|
|
messageList,
|
|
@@ -86,6 +97,8 @@ import EmojiData from '../../../../assets/emojidata/emoji-data.json';
|
|
|
import RE from '../../../../utils/regExp'
|
|
|
import {Toast, Dialog} from "vant"
|
|
|
import useClipboard from "vue-clipboard3";
|
|
|
+import Config from "../../../../config";
|
|
|
+import {useRouter} from 'vue-router';
|
|
|
|
|
|
const {toClipboard} = useClipboard()
|
|
|
|
|
@@ -121,7 +134,8 @@ interface State {
|
|
|
showPopover: boolean,
|
|
|
actions: Obj,
|
|
|
currentAction: StrObj,
|
|
|
- pop: Obj
|
|
|
+ pop: Obj,
|
|
|
+ messageIndex: number
|
|
|
}
|
|
|
|
|
|
export default defineComponent({
|
|
@@ -153,7 +167,8 @@ export default defineComponent({
|
|
|
isShow: false,
|
|
|
left: 0,
|
|
|
top: 0
|
|
|
- }
|
|
|
+ },
|
|
|
+ messageIndex: 0
|
|
|
})
|
|
|
|
|
|
const optionsName = {
|
|
@@ -172,6 +187,7 @@ export default defineComponent({
|
|
|
const messageListDom = ref<HTMLElement | null>(null)
|
|
|
|
|
|
const store = useStore()
|
|
|
+ const router = useRouter()
|
|
|
const friendName = computed(() => store.state.chatUserInfo.friendName)
|
|
|
|
|
|
const showInfo = () => {
|
|
@@ -227,17 +243,13 @@ export default defineComponent({
|
|
|
state.page = 1
|
|
|
state.messageList = []
|
|
|
getMessageList()
|
|
|
- })
|
|
|
+ }, {immediate: true})
|
|
|
|
|
|
- watch(() => store.state.isShowChat, val => {
|
|
|
- if (val) {
|
|
|
- nextTick(() => {
|
|
|
- (messageContentDom.value as HTMLElement).onscroll = (ev: any) => {
|
|
|
- if (ev.target.scrollTop === 0) {
|
|
|
- getMessageList();
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
+ onMounted(() => {
|
|
|
+ (messageContentDom.value as HTMLElement).onscroll = (ev: any) => {
|
|
|
+ if (ev.target.scrollTop === 0) {
|
|
|
+ getMessageList();
|
|
|
+ }
|
|
|
}
|
|
|
})
|
|
|
|
|
@@ -288,7 +300,6 @@ export default defineComponent({
|
|
|
})
|
|
|
|
|
|
const sendMsg = async () => {
|
|
|
- document.getElementById('textarea')?.focus()
|
|
|
let content = state.message.trim()
|
|
|
// 把表情包转成:__表情包的英文名字__
|
|
|
content = content.replace(RE.emoji, (a, emoji) => `__${emojiMap[emoji.codePointAt(0)]}__`)
|
|
@@ -304,6 +315,7 @@ export default defineComponent({
|
|
|
}
|
|
|
state.message = ''
|
|
|
state.messageList.push(data)
|
|
|
+ document.getElementById('textarea')?.focus()
|
|
|
nextTick(() => {
|
|
|
scrollToBottom()
|
|
|
})
|
|
@@ -366,7 +378,6 @@ export default defineComponent({
|
|
|
await deleteFriend({id: chatUserInfo.friendId})
|
|
|
let i = store.state.userList.indexOf(chatUserInfo)
|
|
|
store.state.userList.splice(i, 1)
|
|
|
- store.commit('setIsShowChat', false)
|
|
|
store.commit('setIsShowRight', false)
|
|
|
Toast.success('删除成功')
|
|
|
})
|
|
@@ -383,52 +394,50 @@ export default defineComponent({
|
|
|
})
|
|
|
let i = store.state.userList.indexOf(chatUserInfo)
|
|
|
store.state.userList.splice(i, 1)
|
|
|
- store.commit('setIsShowChat', false)
|
|
|
store.commit('setIsShowRight', false)
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- let messageHtml: string
|
|
|
- let messageIndex: number
|
|
|
- let timer: any
|
|
|
const onContextmenu = (event: any, index: number) => {
|
|
|
event.preventDefault() // 阻止默认的右键菜单弹出
|
|
|
showPop(event, index)
|
|
|
};
|
|
|
|
|
|
+ let popTimer: any
|
|
|
const onTouchstart = (event: any, index: number) => {
|
|
|
- timer = setTimeout(() => {
|
|
|
+ popTimer = setTimeout(() => {
|
|
|
showPop(event, index)
|
|
|
}, 1000)
|
|
|
}
|
|
|
|
|
|
const onTouchend = () => {
|
|
|
- clearTimeout(timer)
|
|
|
+ clearTimeout(popTimer)
|
|
|
}
|
|
|
|
|
|
+ let messageText: string
|
|
|
const showPop = (event: any, index: number) => {
|
|
|
state.pop = {
|
|
|
isShow: true,
|
|
|
left: event.clientX + 'px',
|
|
|
top: event.clientY + 'px'
|
|
|
}
|
|
|
- messageHtml = event.target.innerText
|
|
|
- messageIndex = index
|
|
|
+ messageText = event.target.innerText
|
|
|
+ state.messageIndex = index
|
|
|
}
|
|
|
|
|
|
const copy = () => {
|
|
|
closePop()
|
|
|
- toClipboard(messageHtml)
|
|
|
+ toClipboard(messageText)
|
|
|
}
|
|
|
|
|
|
const removeMessage = async () => {
|
|
|
closePop()
|
|
|
const pageSize = 20 // 后端默认每页20条数据
|
|
|
- const total = state.messageList.length - messageIndex
|
|
|
+ const total = state.messageList.length - state.messageIndex
|
|
|
const page = Math.ceil(total / pageSize)
|
|
|
let chatUserInfo = store.state.chatUserInfo
|
|
|
- let id = state.messageList[messageIndex].id
|
|
|
+ let id = state.messageList[state.messageIndex].id
|
|
|
if (id === 0) {
|
|
|
let {data} = await messageList({
|
|
|
fromId: store.state.userInfo.id,
|
|
@@ -436,14 +445,14 @@ export default defineComponent({
|
|
|
messageType: store.state.chatUserInfo.isGroup,
|
|
|
page,
|
|
|
})
|
|
|
- id = data.find((item: Obj) => item.content === state.messageList[messageIndex].content)?.id
|
|
|
+ id = data.find((item: Obj) => item.content === state.messageList[state.messageIndex].content)?.id
|
|
|
}
|
|
|
await deleteMessage({
|
|
|
toId: chatUserInfo.friendId,
|
|
|
messageType: chatUserInfo.isGroup,
|
|
|
msgId: [id]
|
|
|
})
|
|
|
- state.messageList.splice(messageIndex, 1)
|
|
|
+ state.messageList.splice(state.messageIndex, 1)
|
|
|
}
|
|
|
|
|
|
const closePop = () => {
|
|
@@ -456,10 +465,10 @@ export default defineComponent({
|
|
|
window.removeEventListener('click', closePop)
|
|
|
})
|
|
|
|
|
|
-
|
|
|
return {
|
|
|
...toRefs(state),
|
|
|
store,
|
|
|
+ router,
|
|
|
messageContentDom,
|
|
|
messageListDom,
|
|
|
friendName,
|
|
@@ -473,7 +482,8 @@ export default defineComponent({
|
|
|
copy,
|
|
|
removeMessage,
|
|
|
onTouchstart,
|
|
|
- onTouchend
|
|
|
+ onTouchend,
|
|
|
+ Config
|
|
|
}
|
|
|
}
|
|
|
})
|
|
@@ -498,6 +508,11 @@ export default defineComponent({
|
|
|
height: 100%;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
+
|
|
|
+ &.phone {
|
|
|
+ width: 100%;
|
|
|
+ border-right: none;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
.message-top {
|
|
@@ -543,7 +558,6 @@ export default defineComponent({
|
|
|
.message {
|
|
|
//color: royalblue;
|
|
|
color: #07c160;
|
|
|
- display: inline-block;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -563,10 +577,15 @@ export default defineComponent({
|
|
|
}
|
|
|
|
|
|
.message {
|
|
|
+ display: inline-block;
|
|
|
word-break: break-all;
|
|
|
text-align: justify;
|
|
|
-webkit-user-select: none;
|
|
|
user-select: none;
|
|
|
+
|
|
|
+ &.bg {
|
|
|
+ background: #dbdbdb;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -625,17 +644,4 @@ export default defineComponent({
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-@media screen and (max-width: 768px) {
|
|
|
- .chat {
|
|
|
- width: 100%;
|
|
|
- border-right: none;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-@media screen and (min-width: 769px) {
|
|
|
- .close-icon {
|
|
|
- display: none;
|
|
|
- }
|
|
|
-}
|
|
|
</style>
|