修改:移动到 IM 文件夹
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 9.0 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 123 KiB |
Before Width: | Height: | Size: 169 KiB After Width: | Height: | Size: 169 KiB |
3
src/components/Im/SearchInput/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import SearchInput from './src/SearchInput.vue'
|
||||||
|
|
||||||
|
export { SearchInput }
|
3
src/components/Im/UserStatus/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import UserStatus from './src/UserStatus.vue'
|
||||||
|
|
||||||
|
export { UserStatus }
|
3
src/components/Im/Welcome/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import Welcome from './src/Welcome.vue'
|
||||||
|
|
||||||
|
export { Welcome }
|
@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import tang from '@/assets/imgs/welcome/Group 78@3x.png'
|
import tang from '@/assets/imgs/im/welcome/Group 78@3x.png'
|
||||||
import maskGroup from '@/assets/imgs/welcome/Mask_group2.png'
|
import maskGroup from '@/assets/imgs/im/welcome/Mask_group2.png'
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="app_contanier">
|
<div class="app_contanier">
|
@ -1,3 +0,0 @@
|
|||||||
import Chat from './src/Chat.vue'
|
|
||||||
|
|
||||||
export { Chat }
|
|
3
src/layout/components/ImChat/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import ImChat from './src/ImChat.vue'
|
||||||
|
|
||||||
|
export { ImChat }
|
@ -4,7 +4,7 @@ import { ref } from 'vue'
|
|||||||
import IM from '@/views/im/index.vue'
|
import IM from '@/views/im/index.vue'
|
||||||
import { useRouter } from 'vue-router' // 导入 useRouter 方法
|
import { useRouter } from 'vue-router' // 导入 useRouter 方法
|
||||||
|
|
||||||
defineOptions({ name: 'Chat' })
|
defineOptions({ name: 'ImChat' })
|
||||||
|
|
||||||
const dialogVisible = ref(false)
|
const dialogVisible = ref(false)
|
||||||
const router = useRouter() // 创建 router 实例
|
const router = useRouter() // 创建 router 实例
|
@ -1,7 +1,7 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { defineComponent, computed } from 'vue'
|
import { defineComponent, computed } from 'vue'
|
||||||
import { Message } from '@/layout/components//Message'
|
import { Message } from '@/layout/components/Message'
|
||||||
import { Chat } from '@/layout/components/Chat'
|
import { ImChat } from '@/layout/components/ImChat'
|
||||||
import { Collapse } from '@/layout/components/Collapse'
|
import { Collapse } from '@/layout/components/Collapse'
|
||||||
import { UserInfo } from '@/layout/components/UserInfo'
|
import { UserInfo } from '@/layout/components/UserInfo'
|
||||||
import { Screenfull } from '@/layout/components/Screenfull'
|
import { Screenfull } from '@/layout/components/Screenfull'
|
||||||
@ -79,7 +79,7 @@ export default defineComponent({
|
|||||||
{message.value ? (
|
{message.value ? (
|
||||||
<Message class="custom-hover" color="var(--top-header-text-color)"></Message>
|
<Message class="custom-hover" color="var(--top-header-text-color)"></Message>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
<Chat class="custom-hover" color="var(--top-header-text-color)"></Chat>
|
<ImChat class="custom-hover" color="var(--top-header-text-color)"></ImChat>
|
||||||
<UserInfo></UserInfo>
|
<UserInfo></UserInfo>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import { formatDate } from '@/utils/formatTime'
|
import { formatDate } from '@/utils/formatTime'
|
||||||
import { reactive } from 'vue'
|
import { reactive } from 'vue'
|
||||||
/* 头像相关 */
|
/* 头像相关 */
|
||||||
import informIcon from '@/assets/imgs/avatar/inform.png'
|
import informIcon from '@/assets/imgs/im/avatar/inform.png'
|
||||||
/* route */
|
/* route */
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
/* router */
|
/* router */
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
/* 搜索框组件 */
|
/* 搜索框组件 */
|
||||||
import SearchInput from '@/components/SearchInput/index.vue'
|
import { SearchInput } from '@/components/Im/SearchInput'
|
||||||
/* 欢迎页 */
|
/* 欢迎页 */
|
||||||
import Welcome from '@/components/Welcome/index.vue'
|
import { Welcome } from '@/components/Im/Welcome'
|
||||||
import ConversationList from '../Conversation/components/ConversationList.vue'
|
import ConversationList from '../Conversation/components/ConversationList.vue'
|
||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ const toChatMessage = (id, chatType) => {
|
|||||||
<!-- 搜索组件 -->
|
<!-- 搜索组件 -->
|
||||||
<SearchInput :searchType="'conversation'" />
|
<SearchInput :searchType="'conversation'" />
|
||||||
<div class="chat_conversation_list">
|
<div class="chat_conversation_list">
|
||||||
<ConversationList @toInformDetails="toInformDetails" @toChatMessage="toChatMessage" />
|
<ConversationList @to-inform-details="toInformDetails" @to-chat-message="toChatMessage" />
|
||||||
</div>
|
</div>
|
||||||
</el-aside>
|
</el-aside>
|
||||||
<el-main class="chat_conversation_main_box">
|
<el-main class="chat_conversation_main_box">
|
||||||
|
@ -1,16 +1,21 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ElLoading, ElMessageBox } from 'element-plus'
|
import { ElLoading, ElMessageBox } from 'element-plus'
|
||||||
import { emojis } from '@/constant'
|
import { emojis } from '@/constant/im'
|
||||||
import { messageType } from '@/constant'
|
import { messageType } from '@/constant/im'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
import { onClickOutside } from '@vueuse/core'
|
||||||
/* 组件 */
|
/* 组件 */
|
||||||
import PreviewSendImg from '../suit/previewSendImg.vue'
|
import PreviewSendImg from '../suit/previewSendImg.vue'
|
||||||
import VueAt from 'vue-at/dist/vue-at-textarea' // for textarea
|
import VueAt from 'vue-at/dist/vue-at-textarea' // for textarea
|
||||||
const { ALL_MESSAGE_TYPE, CHAT_TYPE, MENTION_ALL } = messageType
|
const props = defineProps({
|
||||||
const nowPickInfo = ref({
|
nowPickInfo: {
|
||||||
id: '',
|
type: Object,
|
||||||
chatType: ''
|
required: true,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
const { ALL_MESSAGE_TYPE, CHAT_TYPE, MENTION_ALL } = messageType
|
||||||
|
const { nowPickInfo } = toRefs(props)
|
||||||
const atMembersList = ref([])
|
const atMembersList = ref([])
|
||||||
//附件类上传加载状态
|
//附件类上传加载状态
|
||||||
const loadingBox = ref(null)
|
const loadingBox = ref(null)
|
||||||
@ -56,6 +61,9 @@ const checkAtMembers = (text) => {
|
|||||||
//emojis框展开
|
//emojis框展开
|
||||||
const isShowEmojisBox = ref(false)
|
const isShowEmojisBox = ref(false)
|
||||||
const emojisBox = ref(null)
|
const emojisBox = ref(null)
|
||||||
|
onClickOutside(emojisBox, () => {
|
||||||
|
isShowEmojisBox.value = false
|
||||||
|
})
|
||||||
const showEmojisBox = () => {
|
const showEmojisBox = () => {
|
||||||
console.log('>>>>>展开模态框')
|
console.log('>>>>>展开模态框')
|
||||||
isShowEmojisBox.value = true
|
isShowEmojisBox.value = true
|
||||||
@ -286,6 +294,9 @@ const sendFilesMessages = async () => {
|
|||||||
const isHttps = window.location.protocol === 'https:' || window.location.hostname === 'localhost'
|
const isHttps = window.location.protocol === 'https:' || window.location.hostname === 'localhost'
|
||||||
const isShowRecordBox = ref(false)
|
const isShowRecordBox = ref(false)
|
||||||
const recordBox = ref(null)
|
const recordBox = ref(null)
|
||||||
|
onClickOutside(recordBox, () => {
|
||||||
|
isShowRecordBox.value = false
|
||||||
|
})
|
||||||
const showRecordBox = () => {
|
const showRecordBox = () => {
|
||||||
isShowRecordBox.value = true
|
isShowRecordBox.value = true
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
import { formatDate } from '@/utils/formatTime'
|
import { formatDate } from '@/utils/formatTime'
|
||||||
/* 默认头像 */
|
/* 默认头像 */
|
||||||
import defaultAvatar from '@/assets/imgs/avatar.gif'
|
import defaultAvatar from '@/assets/imgs/avatar.gif'
|
||||||
|
/* emits */
|
||||||
|
const emit = defineEmits(['scroll-message-list', 're-edit-message', 'message-quote'])
|
||||||
const messageData = ref([
|
const messageData = ref([
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
@ -107,6 +108,10 @@ const startplayAudio = (msgBody) => {
|
|||||||
audioPlayStatus.playMsgId = ''
|
audioPlayStatus.playMsgId = ''
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
//父组件重新编辑方法
|
||||||
|
const reEdit = (msg) => emit('reEditMessage', msg)
|
||||||
|
//调用父组件引用消息
|
||||||
|
const onMsgQuote = (msg) => emit('messageQuote', msg)
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
|
@ -102,7 +102,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat_message_inputbar {
|
.chat_message_input_bar {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 25%;
|
height: 25%;
|
||||||
|
@ -1,7 +1,14 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import UserStatus from '@/components/UserStatus/index.vue'
|
import { UserStatus } from '@/components/Im/UserStatus'
|
||||||
|
import { messageType } from '@/constant/im'
|
||||||
|
/* 组件 */
|
||||||
import MessageList from './components/messageList/index.vue'
|
import MessageList from './components/messageList/index.vue'
|
||||||
import InputBox from './components/inputBox/index.vue'
|
import InputBox from './components/inputBox/index.vue'
|
||||||
|
|
||||||
|
const { push, currentRoute } = useRouter() // 路由
|
||||||
|
const { query } = useRoute() // 查询参数
|
||||||
|
|
||||||
|
const { CHAT_TYPE } = messageType
|
||||||
/* header 操作 */
|
/* header 操作 */
|
||||||
const drawer = ref(false) //抽屉显隐
|
const drawer = ref(false) //抽屉显隐
|
||||||
const handleDrawer = () => {
|
const handleDrawer = () => {
|
||||||
@ -19,7 +26,7 @@ const delTheFriend = () => {
|
|||||||
// 当前聊天对象信息
|
// 当前聊天对象信息
|
||||||
const nowPickInfo = ref({
|
const nowPickInfo = ref({
|
||||||
id: '1',
|
id: '1',
|
||||||
chatType: 1,
|
chatType: CHAT_TYPE.SINGLE,
|
||||||
userInfo: {
|
userInfo: {
|
||||||
nickname: '好友1',
|
nickname: '好友1',
|
||||||
userStatus: '1'
|
userStatus: '1'
|
||||||
@ -41,6 +48,24 @@ const messageData = computed(() => [
|
|||||||
type: 'text'
|
type: 'text'
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
//监听路由改变获取对应的getIdInfo
|
||||||
|
const stopWatchRoute = watch(
|
||||||
|
() => query,
|
||||||
|
(routeVal) => {
|
||||||
|
console.log('>>>>>>>>监听到路由参数变化', routeVal)
|
||||||
|
if (routeVal) {
|
||||||
|
// nowPickInfo.value = { ...routeVal }
|
||||||
|
// loginState.value && getIdInfo(routeVal)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
//离开该路由销毁route监听
|
||||||
|
onBeforeRouteLeave(() => {
|
||||||
|
stopWatchRoute()
|
||||||
|
})
|
||||||
/* 消息相关 */
|
/* 消息相关 */
|
||||||
const loadingHistoryMsg = ref(false) //是否正在加载中
|
const loadingHistoryMsg = ref(false) //是否正在加载中
|
||||||
const isMoreHistoryMsg = ref(true) //加载文案展示为加载更多还是已无更多。
|
const isMoreHistoryMsg = ref(true) //加载文案展示为加载更多还是已无更多。
|
||||||
@ -64,46 +89,15 @@ const messageQuote = (msg) => inputBox.value.handleQuoteMessage(msg)
|
|||||||
<template>
|
<template>
|
||||||
<el-container class="app_container">
|
<el-container class="app_container">
|
||||||
<el-header class="chat_message_header">
|
<el-header class="chat_message_header">
|
||||||
<template v-if="nowPickInfo.chatType === 1">
|
<template v-if="nowPickInfo.chatType === CHAT_TYPE.SINGLE">
|
||||||
<div v-if="nowPickInfo.userInfo" class="chat_user_box">
|
<div v-if="nowPickInfo.userInfo" class="chat_user_box">
|
||||||
<span class="chat_user_name"> {{ nowPickInfo.userInfo.nickname || nowPickInfo.id }}</span>
|
<span class="chat_user_name"> {{ nowPickInfo.userInfo.nickname || nowPickInfo.id }}</span>
|
||||||
<UserStatus :userStatus="nowPickInfo.userInfo.userStatus" />
|
<UserStatus :userStatus="nowPickInfo.userInfo.userStatus" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else> {{ nowPickInfo.id }}<span style="font-size: 10px">(非好友)</span> </div>
|
<div v-else> {{ nowPickInfo.id }}<span style="font-size: 10px">(非好友)</span> </div>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="nowPickInfo.chatType === 2">
|
|
||||||
<div v-if="nowPickInfo.groupDetail" class="chat_user_box">
|
|
||||||
<span class="chat_user_name">
|
|
||||||
{{ groupDetail.name || '' }}
|
|
||||||
{{ `(${groupDetail?.affiliations_count || ''})` }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div v-else class="chat_user_box">
|
|
||||||
<span class="chat_user_name">
|
|
||||||
{{ groupDetail.name || nowPickInfo.id }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<!-- 群组展示抽屉 -->
|
|
||||||
<span
|
|
||||||
class="more"
|
|
||||||
v-if="nowPickInfo.groupDetail && nowPickInfo.chatType === 2"
|
|
||||||
@click="handleDrawer"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
width="18"
|
|
||||||
height="4"
|
|
||||||
viewBox="0 0 18 4"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<circle cx="2" cy="2" r="2" fill="#333333" />
|
|
||||||
<circle cx="9" cy="2" r="2" fill="#333333" />
|
|
||||||
<circle cx="16" cy="2" r="2" fill="#333333" />
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
<!-- 单人展示删除拉黑 -->
|
<!-- 单人展示删除拉黑 -->
|
||||||
<span class="more" v-if="nowPickInfo.chatType === 1">
|
<span class="more" v-if="nowPickInfo.chatType === CHAT_TYPE.SINGLE">
|
||||||
<el-dropdown placement="bottom-end" trigger="click">
|
<el-dropdown placement="bottom-end" trigger="click">
|
||||||
<svg
|
<svg
|
||||||
width="18"
|
width="18"
|
||||||
@ -149,31 +143,16 @@ const messageQuote = (msg) => inputBox.value.handleQuoteMessage(msg)
|
|||||||
<MessageList
|
<MessageList
|
||||||
:nowPickInfo="nowPickInfo"
|
:nowPickInfo="nowPickInfo"
|
||||||
:messageData="messageData"
|
:messageData="messageData"
|
||||||
@scrollMessageList="scrollMessageList"
|
@scroll-message-list="scrollMessageList"
|
||||||
@reEditMessage="reEditMessage"
|
@re-edit-message="reEditMessage"
|
||||||
@messageQuote="messageQuote"
|
@message-quote="messageQuote"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
</el-main>
|
</el-main>
|
||||||
<el-footer class="chat_message_inputbar">
|
<el-footer class="chat_message_input_bar">
|
||||||
<InputBox ref="inputBox" :nowPickInfo="nowPickInfo" />
|
<InputBox ref="inputBox" :nowPickInfo="nowPickInfo" />
|
||||||
</el-footer>
|
</el-footer>
|
||||||
<el-drawer
|
|
||||||
v-if="nowPickInfo.chatType === 2"
|
|
||||||
v-model="drawer"
|
|
||||||
:show-close="false"
|
|
||||||
:close-on-click-modal="true"
|
|
||||||
direction="rtl"
|
|
||||||
:modal="true"
|
|
||||||
size="280px"
|
|
||||||
>
|
|
||||||
<GroupsDetails
|
|
||||||
:nowGroupId="nowPickInfo.id"
|
|
||||||
:groupDetail="groupDetail"
|
|
||||||
@handleDrawer="handleDrawer"
|
|
||||||
/>
|
|
||||||
</el-drawer>
|
|
||||||
</el-container>
|
</el-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -3,10 +3,10 @@
|
|||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
/* 取用户头像 */
|
/* 取用户头像 */
|
||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
import highlightConversation from '@/assets/imgs/tabbar/highlightconversation.png'
|
import highlightConversation from '@/assets/imgs/im/tabbar/highlightconversation.png'
|
||||||
import grayConversation from '@/assets/imgs/tabbar/grayconversation.png'
|
import grayConversation from '@/assets/imgs/im/tabbar/grayconversation.png'
|
||||||
import highlightContacts from '@/assets/imgs/tabbar/higtlightcontacts.png'
|
import highlightContacts from '@/assets/imgs/im/tabbar/higtlightcontacts.png'
|
||||||
import grayContacts from '@/assets/imgs/tabbar/graycontacts.png'
|
import grayContacts from '@/assets/imgs/im/tabbar/graycontacts.png'
|
||||||
import avatarImg from '@/assets/imgs/avatar.gif'
|
import avatarImg from '@/assets/imgs/avatar.gif'
|
||||||
import { useUserStore } from '@/store/modules/user'
|
import { useUserStore } from '@/store/modules/user'
|
||||||
|
|
||||||
|