|
@@ -24,7 +24,7 @@
|
|
|
<li class="item"
|
|
|
:class="{self: item.fromUserId === store.state.userInfo.id}"
|
|
|
:key="item.createdAt"
|
|
|
- v-for="item in messageList">
|
|
|
+ v-for="(item,index) in messageList">
|
|
|
<div class="common-pic">
|
|
|
<template v-if="item.fromUserId === store.state.userInfo.id">
|
|
|
<img :src="store.state.userInfo.avatar" alt="" v-if="store.state.userInfo.avatar">
|
|
@@ -34,7 +34,7 @@
|
|
|
</div>
|
|
|
<div class="warp">
|
|
|
<!-- <div class="username">{{ item.fromUsername }}</div>-->
|
|
|
- <div class="message" v-html="messageFormat(item.content)"/>
|
|
|
+ <div class="message" @contextmenu="onContextmenu($event,index)" v-html="messageFormat(item.content)"/>
|
|
|
<div class="time">{{ formatDateTime(item.createdAt) }}</div>
|
|
|
</div>
|
|
|
</li>
|
|
@@ -58,6 +58,10 @@
|
|
|
</van-button>
|
|
|
</div>
|
|
|
</div>
|
|
|
+ <div class="custom-popover" v-if="pop.isShow" :style="{left: pop.left, top: pop.top}">
|
|
|
+ <div class="item" @click="copy">复制</div>
|
|
|
+ <div class="item" @click="removeMessage">删除</div>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts">
|
|
@@ -113,6 +117,7 @@ interface State {
|
|
|
showPopover: boolean,
|
|
|
actions: Obj,
|
|
|
currentAction: StrObj,
|
|
|
+ pop: Obj
|
|
|
}
|
|
|
|
|
|
export default defineComponent({
|
|
@@ -139,7 +144,12 @@ export default defineComponent({
|
|
|
{value: 'exitGroup', text: '离开群'},
|
|
|
],
|
|
|
},
|
|
|
- currentAction: {}
|
|
|
+ currentAction: {},
|
|
|
+ pop: {
|
|
|
+ isShow: false,
|
|
|
+ left: 0,
|
|
|
+ top: 0
|
|
|
+ }
|
|
|
})
|
|
|
|
|
|
const optionsName = {
|
|
@@ -154,10 +164,6 @@ export default defineComponent({
|
|
|
Activities: '活动'
|
|
|
}
|
|
|
|
|
|
- const clickEmoji = (val: any) => {
|
|
|
- console.log(val);
|
|
|
- };
|
|
|
-
|
|
|
const messageContentDom = ref<HTMLElement | null>(null)
|
|
|
const messageListDom = ref<HTMLElement | null>(null)
|
|
|
|
|
@@ -179,8 +185,8 @@ export default defineComponent({
|
|
|
fromId: store.state.userInfo.id,
|
|
|
toId: store.state.chatUserInfo.friendId,
|
|
|
messageType: store.state.chatUserInfo.isGroup,
|
|
|
- ToUsername: store.state.chatUserInfo.friendName,
|
|
|
- page: state.page
|
|
|
+ // ToUsername: store.state.chatUserInfo.friendName,
|
|
|
+ page: state.page,
|
|
|
}).then(({data}) => {
|
|
|
data = data || []
|
|
|
if (data.length < 20) {
|
|
@@ -336,18 +342,15 @@ export default defineComponent({
|
|
|
if (action.value === 'deleteMessage') {
|
|
|
Dialog.confirm({
|
|
|
title: '温馨提示',
|
|
|
- message: '确定要删除聊天记录吗?',
|
|
|
+ message: '确定要删除所有聊天记录吗?',
|
|
|
}).then(async () => {
|
|
|
Toast('删除中...')
|
|
|
- let {data} = await messageList({
|
|
|
- fromId: store.state.userInfo.id,
|
|
|
- toId: store.state.chatUserInfo.friendId,
|
|
|
- messageType: store.state.chatUserInfo.isGroup,
|
|
|
- ToUsername: store.state.chatUserInfo.friendName,
|
|
|
- page: 1,
|
|
|
- pageSize: state.messageList.length
|
|
|
+ await deleteMessage({
|
|
|
+ toId: chatUserInfo.friendId,
|
|
|
+ messageType: chatUserInfo.isGroup,
|
|
|
+ msgId: [],
|
|
|
+ isClearUp: true,
|
|
|
})
|
|
|
- await deleteMessage({msgId: data.map((item: Obj) => item.id)})
|
|
|
state.messageList = []
|
|
|
Toast.success('删除成功')
|
|
|
})
|
|
@@ -355,7 +358,7 @@ export default defineComponent({
|
|
|
if (action.value === 'deleteFriend') {
|
|
|
Dialog.confirm({
|
|
|
title: '温馨提示',
|
|
|
- message: `确定删除${chatUserInfo.username}吗?`
|
|
|
+ message: `确定删除${chatUserInfo.friendName}吗?`
|
|
|
}).then(async () => {
|
|
|
await deleteFriend({id: chatUserInfo.friendId})
|
|
|
let i = store.state.userList.indexOf(chatUserInfo)
|
|
@@ -383,19 +386,56 @@ export default defineComponent({
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- const handleKeydown = (e: KeyboardEvent) => {
|
|
|
- if (state.message.trim() && !e.shiftKey && e.key === 'Enter') {
|
|
|
- document.getElementById('textarea')?.blur()
|
|
|
- sendMsg()
|
|
|
+ let messageHtml: string
|
|
|
+ let messageIndex: number
|
|
|
+ const onContextmenu = (event: any, index: number) => {
|
|
|
+ event.preventDefault(); // 阻止默认的右键菜单弹出
|
|
|
+ state.pop = {
|
|
|
+ isShow: true,
|
|
|
+ left: event.clientX + 'px',
|
|
|
+ top: event.clientY + 'px'
|
|
|
}
|
|
|
+ messageHtml = event.target.innerHTML
|
|
|
+ messageIndex = index
|
|
|
+ };
|
|
|
+
|
|
|
+ const copy = () => {
|
|
|
+ closePop()
|
|
|
+ toClipboard(messageHtml)
|
|
|
+ }
|
|
|
+
|
|
|
+ const removeMessage = async () => {
|
|
|
+ closePop()
|
|
|
+ const pageSize = 20 // 后端默认每页20条数据
|
|
|
+ const total = state.messageList.length - messageIndex
|
|
|
+ const page = Math.ceil(total / pageSize)
|
|
|
+ let chatUserInfo = store.state.chatUserInfo
|
|
|
+ let {data} = await messageList({
|
|
|
+ fromId: store.state.userInfo.id,
|
|
|
+ toId: store.state.chatUserInfo.friendId,
|
|
|
+ messageType: store.state.chatUserInfo.isGroup,
|
|
|
+ page,
|
|
|
+ })
|
|
|
+ const id = data.find((item: Obj) => item.content === state.messageList[messageIndex].content)?.id
|
|
|
+ await deleteMessage({
|
|
|
+ toId: chatUserInfo.friendId,
|
|
|
+ messageType: chatUserInfo.isGroup,
|
|
|
+ msgId: [id]
|
|
|
+ })
|
|
|
+ state.messageList.splice(messageIndex, 1)
|
|
|
+ }
|
|
|
+
|
|
|
+ const closePop = () => {
|
|
|
+ state.pop.isShow = false
|
|
|
}
|
|
|
|
|
|
- window.addEventListener('keydown', handleKeydown)
|
|
|
+ window.addEventListener('click', closePop)
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
- window.removeEventListener('keydown', handleKeydown)
|
|
|
+ window.removeEventListener('click', closePop)
|
|
|
})
|
|
|
|
|
|
+
|
|
|
return {
|
|
|
...toRefs(state),
|
|
|
store,
|
|
@@ -408,7 +448,9 @@ export default defineComponent({
|
|
|
optionsName,
|
|
|
messageFormat,
|
|
|
selectAction,
|
|
|
- clickEmoji
|
|
|
+ onContextmenu,
|
|
|
+ copy,
|
|
|
+ removeMessage
|
|
|
}
|
|
|
}
|
|
|
})
|
|
@@ -541,6 +583,24 @@ export default defineComponent({
|
|
|
margin-left: 10px;
|
|
|
}
|
|
|
|
|
|
+.custom-popover {
|
|
|
+ position: fixed;
|
|
|
+ padding: 3px;
|
|
|
+ border-radius: 6px;
|
|
|
+ background: #fff;
|
|
|
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
|
|
|
+
|
|
|
+ .item {
|
|
|
+ padding: 8px 20px;
|
|
|
+ border-radius: 6px;
|
|
|
+ white-space: nowrap;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background: #f1f1f1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
@media screen and (max-width: 768px) {
|
|
|
.chat {
|
|
|
width: 100%;
|