Files
im/pages/conversation/conversationList/components/ChatHeader.vue
T

312 lines
7.5 KiB
Vue
Raw Normal View History

2025-11-07 09:56:20 +08:00
<template>
2025-11-25 05:36:02 +08:00
<view class="chat_header">
2025-11-27 07:40:32 +08:00
<uni-nav-bar
right-icon="plus"
@clickRight="showMore"
:border="false"
title="标题"
backgroundColor="transparent"
>
<template #right>
2025-12-05 16:10:52 +08:00
<uni-icons @click="showMore" type="plus" size="26" class="more_icon"></uni-icons>
2025-11-27 07:40:32 +08:00
</template>
</uni-nav-bar>
<view class="right_action">
<u-overlay :show="moreMenuVisible" @click="moreMenuVisible = false" opacity="0">
<view :style="{ top: popMenuPosition.top, right: popMenuPosition.right }" class="more_menu">
<view @click="clickMenu({name:'createGroup'})" class="menu_item">
<uni-icons size="24" color="#FFF" type="chat"></uni-icons>
<text>创建群聊</text>
</view>
<view @click="clickMenu({name:'addFriend'})" class="menu_item">
<uni-icons size="24" color="#FFF" type="personadd"></uni-icons>
<text>添加好友</text>
</view>
<view @click="clickMenu({name:'createGroup'})" class="menu_item">
<uni-icons size="24" color="#FFF" type="scan"></uni-icons>
<text>扫一扫</text>
</view>
</view>
</u-overlay>
</view>
2025-12-08 02:29:46 +08:00
<SearchbarPlace @click="toSearch">搜索</SearchbarPlace>
2025-11-27 07:40:32 +08:00
<view class="status_notice">
<view class="tag" v-if="storeIsSyncing">
<img class="loading" style="height: 24rpx; width: 24rpx" src="static/images/loading.png"
alt="" />
<text class="status">同步中</text>
</view>
<view class="tag" v-if="connectStart == 0">
<img class="loading" style="height: 24rpx; width: 24rpx" src="static/images/loading.png"
alt="" />
<text class="status">连接中</text>
</view>
<view class="err-tag" v-if="connectStart == -1">
<img style="height: 24rpx; width: 24rpx" src="static/images/sync_error.png" alt="" />
<text class="status">连接失败</text>
</view>
</view>
<view class="self_info" v-if="1==2">
<my-avatar :src="storeSelfInfo.faceURL" :desc="storeSelfInfo.nickname || storeSelfInfo.remark" size="46" />
2025-11-25 05:36:02 +08:00
<view class="self_info_desc">
<view class="user_state">
2025-11-27 07:40:32 +08:00
<text class="nickname">{{ storeSelfInfo.nickname || storeSelfInfo.remark }}</text>
2025-11-25 05:36:02 +08:00
<view v-if="!storeReinstall">
<view class="tag" v-if="storeIsSyncing">
<img class="loading" style="height: 24rpx; width: 24rpx" src="static/images/loading.png"
alt="" />
<text class="status">同步中</text>
</view>
<view class="tag" v-if="connectStart == 0">
<img class="loading" style="height: 24rpx; width: 24rpx" src="static/images/loading.png"
alt="" />
<text class="status">连接中</text>
</view>
<view class="err-tag" v-if="connectStart == -1">
<img style="height: 24rpx; width: 24rpx" src="static/images/sync_error.png" alt="" />
<text class="status">连接失败</text>
</view>
</view>
</view>
</view>
</view>
2025-11-27 07:40:32 +08:00
2025-11-25 05:36:02 +08:00
</view>
2025-11-07 09:56:20 +08:00
</template>
<script>
2025-11-25 05:36:02 +08:00
import {
mapGetters
} from "vuex";
import MyAvatar from "@/components/MyAvatar/index.vue";
import IMSDK from "openim-uniapp-polyfill";
2025-11-27 07:40:32 +08:00
import util from "@/util";
2025-12-08 02:29:46 +08:00
import SearchbarPlace from "@/components/searchbar_place.vue";
2025-11-25 05:36:02 +08:00
export default {
name: "ChatHeader",
components: {
2025-12-08 02:29:46 +08:00
MyAvatar,SearchbarPlace
2025-11-25 05:36:02 +08:00
},
props: {},
data() {
return {
connectStart: -2,
moreMenuVisible: false,
popMenuPosition: {
top: 0,
right: 0,
2025-11-27 07:40:32 +08:00
}
2025-11-25 05:36:02 +08:00
};
},
computed: {
...mapGetters(["storeSelfInfo", "storeIsSyncing", "storeReinstall"]),
},
mounted() {
this.subscribeAll();
},
beforeDestroy() {
this.unsubscribeAll();
},
methods: {
2025-12-08 02:29:46 +08:00
toSearch(){
uni.navigateTo({
url:"/pages/common/search/index"
})
},
2025-11-25 05:36:02 +08:00
setStateStart() {
this.connectStart = 0;
},
setStateSuccess() {
this.connectStart = 1;
},
setStateError() {
this.connectStart = -1;
},
subscribeAll() {
IMSDK.subscribe(IMSDK.IMEvents.OnConnecting, this.setStateStart);
IMSDK.subscribe(IMSDK.IMEvents.OnConnectSuccess, this.setStateSuccess);
IMSDK.subscribe(IMSDK.IMEvents.OnConnectFailed, this.setStateError);
},
unsubscribeAll() {
IMSDK.unsubscribe(IMSDK.IMEvents.OnConnecting, this.setStateStart);
IMSDK.unsubscribe(IMSDK.IMEvents.OnConnectSuccess, this.setStateSuccess);
IMSDK.unsubscribe(IMSDK.IMEvents.OnConnectFailed, this.setStateError);
},
2025-11-27 07:40:32 +08:00
clickMenu({name}) {
switch (name) {
case 'createGroup':
2025-11-25 05:36:02 +08:00
uni.navigateTo({
2025-11-27 07:40:32 +08:00
url: `/pages/common/createGroup/index`,
2025-11-25 05:36:02 +08:00
});
break;
2025-11-27 07:40:32 +08:00
case 'addFriend':
2025-11-25 05:36:02 +08:00
uni.navigateTo({
2025-12-05 16:10:52 +08:00
url: `/pages/common/searchUserOrGroup/index?isSearchGroup=false`,
2025-11-25 05:36:02 +08:00
});
break;
2025-11-27 07:40:32 +08:00
case 'scan':
util.scan();
break;
2025-11-25 05:36:02 +08:00
default:
break;
}
},
async showMore() {
const {right,bottom} = await this.getEl(".more_icon");
this.popMenuPosition.right =
uni.getWindowInfo().windowWidth - right + "px";
this.popMenuPosition.top = bottom + "px";
this.moreMenuVisible = true;
},
getEl(el) {
return new Promise((resolve) => {
const query = uni.createSelectorQuery().in(this);
query
.select(el)
.boundingClientRect((data) => {
// 存在data,且存在宽和高,视为渲染完毕
resolve(data);
})
.exec();
});
},
},
};
2025-11-07 09:56:20 +08:00
</script>
<style lang="scss" scoped>
2025-11-25 05:36:02 +08:00
@keyframes loading {
0% {
transform: rotate(0deg);
}
2025-11-07 09:56:20 +08:00
2025-11-25 05:36:02 +08:00
100% {
transform: rotate(360deg);
}
}
2025-11-07 09:56:20 +08:00
2025-11-25 05:36:02 +08:00
.chat_header {
2025-11-27 07:40:32 +08:00
@include colBox(true);
padding: 36rpx 24rpx 10rpx;
//margin-top: var(--status-bar-height);
background: #f4f4f4;
2025-11-07 09:56:20 +08:00
2025-11-25 05:36:02 +08:00
.self_info {
@include btwBox();
2025-11-07 09:56:20 +08:00
2025-11-25 05:36:02 +08:00
&_desc {
@include colBox(true);
margin-left: 24rpx;
color: $uni-text-color;
2025-11-07 09:56:20 +08:00
2025-11-25 05:36:02 +08:00
.company {
@include nomalEllipsis();
font-size: 24rpx;
margin-bottom: 10rpx;
max-width: 300rpx;
}
2025-11-07 09:56:20 +08:00
2025-11-25 05:36:02 +08:00
.user_state {
@include vCenterBox();
2025-11-07 09:56:20 +08:00
2025-11-25 05:36:02 +08:00
.nickname {
@include nomalEllipsis();
font-size: 26rpx;
max-width: 240rpx;
}
2025-11-07 09:56:20 +08:00
2025-11-25 05:36:02 +08:00
.err-tag {
display: flex;
justify-content: center;
align-items: center;
width: 152rpx;
height: 44rpx;
background: #ffe1dd;
border-radius: 12rpx 12rpx 12rpx 12rpx;
margin-left: 8rpx;
2025-11-07 09:56:20 +08:00
2025-11-25 05:36:02 +08:00
.status {
font-size: 24rpx;
margin-left: 8rpx;
font-weight: 400;
color: #ff381f;
}
}
2025-11-07 09:56:20 +08:00
2025-11-25 05:36:02 +08:00
.tag {
display: flex;
justify-content: center;
align-items: center;
width: 152rpx;
height: 44rpx;
background: #f2f8ff;
border-radius: 12rpx 12rpx 12rpx 12rpx;
margin-left: 8rpx;
2025-11-07 09:56:20 +08:00
2025-11-25 05:36:02 +08:00
.loading {
animation: loading 1.5s infinite;
}
2025-11-07 09:56:20 +08:00
2025-11-25 05:36:02 +08:00
.status {
font-size: 24rpx;
margin-left: 8rpx;
font-weight: 400;
color: #0089ff;
}
}
2025-11-07 09:56:20 +08:00
2025-11-25 05:36:02 +08:00
.online_state {
@include vCenterBox();
margin-left: 24rpx;
font-size: 24rpx;
2025-11-07 09:56:20 +08:00
2025-11-25 05:36:02 +08:00
.dot {
background-color: #10cc64;
width: 12rpx;
height: 12rpx;
border-radius: 50%;
margin-right: 12rpx;
}
}
}
}
}
2025-11-07 09:56:20 +08:00
2025-11-25 05:36:02 +08:00
.right_action {
display: flex;
position: relative;
2025-11-07 09:56:20 +08:00
2025-11-25 05:36:02 +08:00
.more_menu {
position: absolute;
// bottom: 0;
// left: 100%;
z-index: 999;
// transform: translate(-100%, 100%);
box-shadow: 0px 0px 6px 2px rgba(0, 0, 0, 0.16);
width: max-content;
border-radius: 12rpx;
2025-11-27 07:40:32 +08:00
background-color: rgba(76 ,76, 76, 0.9);
2025-11-07 09:56:20 +08:00
2025-11-25 05:36:02 +08:00
.menu_item {
display: flex;
justify-content: flex-start;
align-items: center;
padding: 20rpx 24rpx;
font-size: 28rpx;
2025-11-27 07:40:32 +08:00
color: #fff;
//border-bottom: 1px solid #f0f0f0;
2025-11-07 09:56:20 +08:00
2025-11-27 07:40:32 +08:00
.uni-icons {
margin-right: 16rpx;
color: #FFF;
2025-11-25 05:36:02 +08:00
}
&:last-child {
border: none;
}
}
}
}
}
</style>