Ai_GirlFriend/xuniYou/pages/friends/index.vue

357 lines
8.1 KiB
Vue
Raw Permalink Normal View History

2026-01-31 19:15:41 +08:00
<template>
<view class="page fc">
<uni-nav-bar fixed statusBar background-color="transparent" :border="false" @clickLeft="back"
title="好友列表"></uni-nav-bar>
<view class="back"></view>
<view class="head fa end">
<image @click="tosearch" src="/static/friends/friends_add.png"></image>
<image @click="tosearch" src="/static/friends/friends_search.png" mode="widthFix"></image>
<view class="head_content" @click="tomessageList">
<image src="/static/friends/friends_message.png" mode="widthFix"></image>
<text class="head_number faj" v-if="requestsInfo">{{ requestsInfo }}</text>
</view>
<view class="head_content" @click="toofficialList">
<image src="/static/friends/friends_messageA.png" mode="widthFix"></image>
<text class="head_number faj" v-if="msgCountInfo">{{ msgCountInfo }}</text>
</view>
</view>
<scroll-view scroll-y="true" class="scroll-view f1" show-scrollbar @scrolltolower="onScrollToLower">
<view class="body">
<view class="list">
<view class="list_content fa" v-for="(item, index) in friendList" :key="index"
@click="toFriendsChat(item)">
<view class="list_avatar">
<image :src="item.friend.avatar ? item.friend.avatar : ''" mode="aspectFill"></image>
<text class="list_round" v-if="item.is_online"></text>
</view>
<view class="list_module f1">
<view class="list_name h1">{{ item.friend.nickname ? item.friend.nickname : '' }}</view>
<view class="list_id h1">ID{{ item.friend.user_number ? item.friend.user_number : '' }}
</view>
</view>
</view>
</view>
<view class="not" v-if="friendList.length == 0">
<image
src="https://nvlovers.oss-cn-qingdao.aliyuncs.com/uploads/20251226/ff9c872002cc5a5c91154cce12e8342c.png"
mode="widthFix"></image>
<view class="not_title">暂无好友</view>
</view>
</view>
</scroll-view>
<tab-bar></tab-bar>
</view>
</template>
<script>
import {
Friend,
MsgCount
} from '@/utils/api.js'
import { getTokenApi, getOnlineApi } from '@/utils/Huanxin.js'
import notHave from '@/components/not-have.vue';
import topSafety from '@/components/top-safety.vue';
import tabBar from '@/components/tab-bar.vue';
import { emConnect, emConversation } from '@/EaseIM/imApis';
import { useLoginStore } from '@/stores/login';
import { useConversationStore } from '@/stores/conversation';
export default {
components: {
notHave,
topSafety,
tabBar,
},
data() {
return {
form: {
page: 1,
},
friendList: [],
msgCountInfo: 0,
requestsInfo: 0,
}
},
onLoad() {
this.getToken() //获取环信token
},
onShow() {
this.page = 1;
this.friendList = [];
this.friend();
this.msgCount();
},
methods: {
setUserTokenToStorage(userId, token) {
const params = {
key: `EM_${userId}_TOKEN`,
data: { token: token },
};
uni.setStorage({ ...params });
},
async getToken() {
getTokenApi({}).then(res => {
if (res.code == 1) {
// if (!uni.getStorageSync('hxtoken')) {
const loginStore = useLoginStore();
let chatUserName = uni.getStorageSync('userinfo').user_number
let token = res.data.access_token
const { loginWithPassword, loginWithAccessToken } = emConnect();
loginWithPassword(String(chatUserName), 'xuni123');
// loginWithAccessToken(chatUserName, token);
uni.setStorage({
key: 'myUsername',
data: chatUserName
});
loginStore.setLoginUserBaseInfos({ loginUserId: chatUserName });
this.setUserTokenToStorage(chatUserName, token);
// }
// uni.setStorageSync('hxtoken', res.data.access_token)
}
})
},
async friend() {
const res = await Friend(this.form)
console.log('Friend 接口返回:', res)
2026-01-31 19:15:41 +08:00
let data = ''
let ids = ''
let onlineData = ''
if (res.code == 1) {
data = res.data.data || []
console.log('解析后的 data:', data)
2026-01-31 19:15:41 +08:00
ids = data.map(item => {
return item.friend_id
});
}
if (ids.length == 0) {
return
}
const onlineRes = await getOnlineApi({
'user_ids': ids.join(',')
})
if (onlineRes.code == 1) {
onlineData = onlineRes.data
data.forEach(item => {
const onlineStatus = onlineData.find(onlineItem => onlineItem.id == item.friend_id)
if (onlineStatus) {
item.is_online = onlineStatus.is_online
} else {
item.is_online = false
}
})
}
this.friendList.push(...data)
},
msgCount() {
MsgCount({}).then(res => {
if (res.code == 1) {
this.msgCountInfo = res.data.msg_count
this.requestsInfo = res.data.requests
} else {
uni.showToast({
title: res.msg,
icon: 'none',
position: 'top'
})
}
})
},
onScrollToLower() {
++this.form.page
console.log('触底事件')
this.friend()
},
tosearch() {
uni.navigateTo({
url: '/pages/friends/search'
})
},
tomessageList() {
uni.navigateTo({
url: '/pages/friends/messageList'
})
},
toofficialList() {
uni.navigateTo({
url: '/pages/friends/officialList'
})
},
toFriendsChat(item) {
const {
fetchConversationFromServer,
removeConversationFromServer,
sendChannelAck,
} = emConversation();
const conversationStore = useConversationStore();
let channel_id = item.friend.user_number
//好友的信息openid
let listener = {
nickname: item.friend.nickname,
headImage: item.friend.avatar, // 头像,自行修改
openid: item.friend.open_id, //获取小程序用户的openId
}
sendChannelAck(channel_id, 'singleChat');
conversationStore.clearConversationUnReadNum(channel_id);
conversationStore.setChattingUserId(channel_id); //存贮当前聊天对象环信账号
conversationStore.setUserId(item.friend_id); //存贮当前聊天对象i用户id
conversationStore.setUserLevel(item.intimacy_level); //存贮当前聊天对象i用户id
conversationStore.setFriendInfo(listener); //存贮当前聊天对象好友信息
let avatarurl = uni.getStorageSync('userinfo').avatar
let friendAvatar = item.friend.avatar
conversationStore.setAvatar(avatarurl);
conversationStore.setFriendAvatar(friendAvatar);
let data = {
id: item.friend_id,
intimacy_level: item.intimacy_level,
avatar: item.friend.avatar,
nickname: item.friend.nickname,
}
uni.navigateTo({
url: '/pages/friends/chat?item=' + encodeURIComponent(JSON.stringify(data))
})
},
}
}
</script>
<style>
page {
background: #F6F8FA;
}
</style>
<style scoped>
.page {
position: relative;
height: 100vh;
overflow: hidden;
}
.scroll-view {
overflow: hidden;
}
.body {
position: relative;
padding: 0 60rpx;
}
.back {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 436rpx;
background: linear-gradient(180deg, #EAD6FF 0%, rgba(255, 255, 255, 0) 100%);
}
.head {
position: relative;
padding: 50rpx 60rpx 0 22rpx;
}
.head image {
position: relative;
margin: 0 0 0 32rpx;
width: 48rpx;
height: 48rpx;
}
.head_content {
position: relative;
}
.head_number {
position: absolute;
right: -26rpx;
top: -30rpx;
padding: 5rpx 15rpx;
font-size: 24rpx;
color: #FFFFFF;
background: #F55726;
border: 3rpx solid #FFFFFF;
border-radius: 100rpx;
}
.list {
position: relative;
padding: 30rpx 0 200rpx 0;
}
.list_content {
position: relative;
margin: 0 0 30rpx 0;
padding: 32rpx 30rpx;
background: #FFFFFF;
border-radius: 16rpx;
}
.list_avatar {
position: relative;
}
.list_avatar image {
width: 96rpx;
height: 96rpx;
display: block;
flex-shrink: 0;
border-radius: 100rpx;
}
.list_round {
position: absolute;
left: 0;
top: 0;
width: 20rpx;
height: 20rpx;
background: #02AD41;
border: 3rpx solid #FFFFFF;
border-radius: 100rpx;
}
.list_module {
position: relative;
margin: 0 0 0 20rpx;
overflow: hidden;
}
.list_name {
font-weight: 500;
font-size: 32rpx;
color: #222222;
line-height: 50rpx;
}
.list_id {
font-weight: 400;
font-size: 28rpx;
color: #B5B5B5;
line-height: 50rpx;
}
.not {
position: relative;
margin: 88rpx 0 0 0;
}
.not image {
width: 344rpx;
display: block;
margin: 0 auto;
}
.not_title {
margin: 14rpx 0 0 0;
font-weight: 400;
font-size: 30rpx;
color: #9E9E9E;
line-height: 50rpx;
text-align: center;
}
</style>