7 changed files with 600 additions and 0 deletions
@ -0,0 +1,117 @@ |
|||
<template> |
|||
<el-dialog title="添加好友" :visible.sync="dialogVisible" width="350px" :before-close="handleClose"> |
|||
<el-input width="200px" placeholder="搜索好友" class="input-with-select" v-model="searchText" @keyup.enter.native="handleSearch()"> |
|||
<el-button slot="append" icon="el-icon-search" @click="handleSearch()"></el-button> |
|||
</el-input> |
|||
<el-scrollbar style="height:400px"> |
|||
<div v-for="(userInfo) in users" :key="userInfo.id"> |
|||
<div class="item"> |
|||
<div class="avatar"> |
|||
<head-image :url="userInfo.headImage"></head-image> |
|||
</div> |
|||
<div class="add-friend-text"> |
|||
<div>{{userInfo.nickName}}</div> |
|||
<div :class="userInfo.online ? 'online-status online':'online-status'">{{ userInfo.online?"[在线]":"[离线]"}}</div> |
|||
</div> |
|||
<el-button type="success" v-show="!isFriend(userInfo.id)" plain @click="onAddFriend(userInfo)">添加</el-button> |
|||
<el-button type="info" v-show="isFriend(userInfo.id)" plain disabled>已添加</el-button> |
|||
</div> |
|||
</div> |
|||
</el-scrollbar> |
|||
</el-dialog> |
|||
</template> |
|||
|
|||
<script> |
|||
import HeadImage from '../common/HeadImage.vue' |
|||
|
|||
|
|||
export default { |
|||
name: "addFriend", |
|||
components:{HeadImage}, |
|||
data() { |
|||
return { |
|||
users: [], |
|||
searchText: "" |
|||
} |
|||
}, |
|||
props: { |
|||
dialogVisible: { |
|||
type: Boolean |
|||
} |
|||
}, |
|||
methods: { |
|||
handleClose() { |
|||
this.$emit("close"); |
|||
}, |
|||
handleSearch() { |
|||
this.$http({ |
|||
url: "/api/user/findByNickName", |
|||
method: "get", |
|||
params: { |
|||
nickName: this.searchText |
|||
} |
|||
}).then((data) => { |
|||
this.users = data; |
|||
}) |
|||
}, |
|||
handleAddFriend(userInfo){ |
|||
this.$http({ |
|||
url: "/api/friend/add", |
|||
method: "post", |
|||
params: { |
|||
friendId: userInfo.id |
|||
} |
|||
}).then((data) => { |
|||
this.$message.success("添加成功,对方已成为您的好友"); |
|||
let friendInfo = { |
|||
friendId:userInfo.id, |
|||
friendNickName: userInfo.nickName, |
|||
friendHeadImage: userInfo.headImage, |
|||
online: userInfo.online |
|||
} |
|||
this.$store.commit("addFriend",friendInfo); |
|||
}) |
|||
}, |
|||
isFriend(userId){ |
|||
let friends = this.$store.state.friendStore.friends; |
|||
let friend = friends.find((f)=> f.friendId==userId); |
|||
return friend != undefined; |
|||
} |
|||
}, |
|||
|
|||
mounted() { |
|||
this.handleSearch(); |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped lang="scss"> |
|||
|
|||
.item { |
|||
height: 80px; |
|||
display: flex; |
|||
position: relative; |
|||
padding-left: 15px; |
|||
align-items: center; |
|||
padding-right: 25px; |
|||
|
|||
.add-friend-text { |
|||
margin-left: 15px; |
|||
line-height: 80px; |
|||
flex: 3; |
|||
display: flex; |
|||
flex-direction: row; |
|||
height: 100%; |
|||
flex-shrink: 0; |
|||
overflow: hidden; |
|||
|
|||
.online-status{ |
|||
font-size: 12px; |
|||
font-weight: 600; |
|||
&.online{ |
|||
color: #5fb878; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,114 @@ |
|||
<template> |
|||
<div class="item" :class="active ? 'active' : ''"> |
|||
<div class="avatar"> |
|||
<head-image :url="friendInfo.friendHeadImage" > </head-image> |
|||
</div> |
|||
<div class="text"> |
|||
<div>{{ friendInfo.friendNickName}}</div> |
|||
<div :class="online ? 'online-status online':'online-status'">{{ online?"[在线]":"[离线]"}}</div> |
|||
</div> |
|||
<div class="close" @click.stop="$emit('del',friendInfo,index)"> |
|||
<i class="el-icon-close" style="border: none; font-size: 20px;color: black;" title="添加好友"></i> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import HeadImage from '../common/HeadImage.vue'; |
|||
|
|||
export default { |
|||
name: "frinedItem", |
|||
components: {HeadImage}, |
|||
data() { |
|||
return { |
|||
} |
|||
}, |
|||
props: { |
|||
friendInfo: { |
|||
type: Object |
|||
}, |
|||
active:{ |
|||
type: Boolean |
|||
}, |
|||
index:{ |
|||
type: Number |
|||
} |
|||
}, |
|||
computed:{ |
|||
online(){ |
|||
return this.$store.state.friendStore.friends[this.index].online; |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scope lang="scss"> |
|||
.item { |
|||
height: 65px; |
|||
display: flex; |
|||
margin-bottom: 1px; |
|||
position: relative; |
|||
padding-left: 15px; |
|||
align-items: center; |
|||
padding-right: 5px; |
|||
background-color: #eeeeee; |
|||
&:hover { |
|||
background-color: #dddddd; |
|||
} |
|||
|
|||
&.active{ |
|||
background-color: #cccccc; |
|||
} |
|||
|
|||
|
|||
.close { |
|||
width: 1.5rem; |
|||
height: 1.5rem; |
|||
right: 10px; |
|||
top: 1.825rem; |
|||
cursor: pointer; |
|||
display: none; |
|||
} |
|||
|
|||
&:hover { |
|||
.close { |
|||
display: block; |
|||
} |
|||
} |
|||
|
|||
.avatar { |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
width: 45px; |
|||
height: 45px; |
|||
} |
|||
|
|||
.text { |
|||
margin-left: 15px; |
|||
flex: 3; |
|||
display: flex; |
|||
flex-direction: column; |
|||
justify-content: space-around; |
|||
height: 100%; |
|||
flex-shrink: 0; |
|||
overflow: hidden; |
|||
&>div { |
|||
display: flex; |
|||
justify-content: flex-start; |
|||
} |
|||
|
|||
.online-status{ |
|||
font-size: 12px; |
|||
font-weight: 600; |
|||
&.online{ |
|||
color: #5fb878; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
.active { |
|||
background-color: #eeeeee; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,8 @@ |
|||
<template> |
|||
</template> |
|||
|
|||
<script> |
|||
</script> |
|||
|
|||
<style> |
|||
</style> |
|||
@ -0,0 +1,88 @@ |
|||
import httpRequest from '../api/httpRequest.js' |
|||
|
|||
export default { |
|||
|
|||
state: { |
|||
friends: [], |
|||
activeIndex: -1, |
|||
timer: null |
|||
}, |
|||
mutations: { |
|||
initFriendStore(state) { |
|||
httpRequest({ |
|||
url: '/api/friend/list', |
|||
method: 'get' |
|||
}).then((friends) => { |
|||
this.commit("setFriends",friends); |
|||
this.commit("refreshOnlineStatus"); |
|||
}) |
|||
}, |
|||
|
|||
setFriends(state, friends) { |
|||
state.friends = friends; |
|||
}, |
|||
updateFriend(state,friendInfo){ |
|||
state.friends.forEach((f,index)=>{ |
|||
if(f.friendId==friendInfo.friendId){ |
|||
state.friends[index] = friendInfo; |
|||
} |
|||
}) |
|||
}, |
|||
activeFriend(state, index) { |
|||
state.activeIndex = index; |
|||
}, |
|||
removeFriend(state, index) { |
|||
state.friends.splice(index, 1); |
|||
}, |
|||
addFriend(state, friendInfo) { |
|||
state.friends.push(friendInfo); |
|||
}, |
|||
refreshOnlineStatus(state){ |
|||
let userIds = []; |
|||
if(state.friends.length ==0){ |
|||
return; |
|||
} |
|||
state.friends.forEach((f)=>{userIds.push(f.friendId)}); |
|||
httpRequest({ |
|||
url: '/api/user/online', |
|||
method: 'get', |
|||
params: {userIds: userIds.join(',')} |
|||
}).then((onlineIds) => { |
|||
this.commit("setOnlineStatus",onlineIds); |
|||
}) |
|||
|
|||
// 30s后重新拉取
|
|||
clearTimeout(state.timer); |
|||
state.timer = setTimeout(()=>{ |
|||
this.commit("refreshOnlineStatus"); |
|||
},30000) |
|||
}, |
|||
setOnlineStatus(state,onlineIds){ |
|||
state.friends.forEach((f)=>{ |
|||
let onlineFriend = onlineIds.find((id)=> f.friendId==id); |
|||
f.online = onlineFriend != undefined; |
|||
}); |
|||
|
|||
let activeFriend = state.friends[state.activeIndex]; |
|||
state.friends.sort((f1,f2)=>{ |
|||
if(f1.online&&!f2.online){ |
|||
return -1; |
|||
} |
|||
if(f2.online&&!f1.online){ |
|||
return 1; |
|||
} |
|||
return 0; |
|||
}); |
|||
|
|||
// 重新排序后,activeIndex指向的好友可能会变化,需要重新指定
|
|||
if(state.activeIndex >=0){ |
|||
state.friends.forEach((f,i)=>{ |
|||
if(f.friendId == activeFriend.friendId){ |
|||
state.activeIndex = i; |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
import httpRequest from '../api/httpRequest.js' |
|||
|
|||
export default { |
|||
|
|||
state: { |
|||
groups: [], |
|||
activeIndex: -1, |
|||
}, |
|||
mutations: { |
|||
initGroupStore(state, userInfo) { |
|||
httpRequest({ |
|||
url: '/api/friends/list', |
|||
method: 'get' |
|||
}).then((friendsList) => { |
|||
this.commit("setFriendsList",friendsList); |
|||
this.commit("refreshOnlineStatus"); |
|||
}) |
|||
}, |
|||
} |
|||
@ -0,0 +1,184 @@ |
|||
<template> |
|||
<el-container> |
|||
<el-aside width="250px" class="l-friend-box"> |
|||
<el-header class="l-friend-header" height="60px"> |
|||
<div class="l-friend-search"> |
|||
<el-input width="200px" placeholder="搜索好友" v-model="searchText"> |
|||
<el-button slot="append" icon="el-icon-search"></el-button> |
|||
</el-input> |
|||
</div> |
|||
<el-button plain icon="el-icon-plus" style="border: none; padding:12px; font-size: 20px;color: black;" title="添加好友" @click="handleShowAddFriend()"></el-button> |
|||
|
|||
<add-friend :dialogVisible="showAddFriend" @close="handleCloseAddFriend"> |
|||
</add-friend> |
|||
</el-header> |
|||
<el-main> |
|||
<div v-for="(friendInfo,index) in $store.state.friendStore.friends" :key="friendInfo.id"> |
|||
<friend-item v-show="friendInfo.friendNickName.startsWith(searchText)" :friendInfo="friendInfo" :index="index" |
|||
:active="index === $store.state.friendStore.activeIndex" @del="handleDelItem(friendInfo,index)" @click.native="handleActiveItem(friendInfo,index)"> |
|||
</friend-item> |
|||
</div> |
|||
</el-main> |
|||
</el-aside> |
|||
<el-container class="r-friend-box"> |
|||
<div v-show="$store.state.friendStore.activeIndex>=0"> |
|||
<div class="user-detail"> |
|||
<head-image class="detail-head-image" :url="activeUserInfo.headImage"></head-image> |
|||
<div class="info-item"> |
|||
<el-descriptions title="好友信息" class="description" :column="1"> |
|||
<el-descriptions-item label="用户名">{{ activeUserInfo.userName }} |
|||
</el-descriptions-item> |
|||
<el-descriptions-item label="昵称">{{ activeUserInfo.nickName }} |
|||
</el-descriptions-item> |
|||
<el-descriptions-item label="性别">{{ activeUserInfo.sex==0?"男":"女" }}</el-descriptions-item> |
|||
<el-descriptions-item label="签名">{{ activeUserInfo.signature }}</el-descriptions-item> |
|||
</el-descriptions> |
|||
</div> |
|||
</div> |
|||
<div class="btn-group"> |
|||
<el-button class="send-btn" @click="handleSendMessage()">发消息</el-button> |
|||
</div> |
|||
</div> |
|||
</el-container> |
|||
</el-container> |
|||
</template> |
|||
|
|||
<script> |
|||
import FriendItem from "../components/friend/FriendItem.vue"; |
|||
import AddFriend from "../components/friend/AddFriend.vue"; |
|||
import HeadImage from "../components/common/HeadImage.vue"; |
|||
|
|||
export default { |
|||
name: "friend", |
|||
components: { |
|||
FriendItem, |
|||
AddFriend, |
|||
HeadImage |
|||
}, |
|||
data() { |
|||
return { |
|||
searchText: "", |
|||
showAddFriend: false, |
|||
activeUserInfo: {} |
|||
} |
|||
}, |
|||
methods: { |
|||
handleShowAddFriend() { |
|||
this.showAddFriend = true; |
|||
}, |
|||
handleCloseAddFriend() { |
|||
this.showAddFriend = false; |
|||
}, |
|||
handleActiveItem(friendInfo, index) { |
|||
this.$store.commit("activeFriend", index); |
|||
this.$http({ |
|||
url: `/api/user/find/${friendInfo.friendId}`, |
|||
method: 'get' |
|||
}).then((userInfo) => { |
|||
this.activeUserInfo = userInfo; |
|||
// 如果发现好友的头像和昵称改了,进行更新 |
|||
if (userInfo.headImageThumb != friendInfo.friendHeadImage || |
|||
userInfo.nickName != friendInfo.friendNickName) { |
|||
this.updateFriendInfo(friendInfo, userInfo, index) |
|||
} |
|||
}) |
|||
}, |
|||
handleDelItem(friendInfo, index) { |
|||
this.$http({ |
|||
url: '/api/friend/delete', |
|||
method: 'delete', |
|||
params: { |
|||
friendId: friendInfo.friendId |
|||
} |
|||
}).then((data) => { |
|||
this.$message.success("删除好友成功"); |
|||
this.$store.commit("removeFriend", index); |
|||
}) |
|||
}, |
|||
handleSendMessage() { |
|||
let userInfo = this.activeUserInfo; |
|||
let chatInfo = { |
|||
type: 'single', |
|||
targetId: userInfo.id, |
|||
showName: userInfo.nickName, |
|||
headImage: userInfo.headImage, |
|||
}; |
|||
this.$store.commit("openChat", chatInfo); |
|||
this.$store.commit("activeChat", 0); |
|||
this.$router.push("/home/chat"); |
|||
}, |
|||
updateFriendInfo(friendInfo, userInfo, index) { |
|||
friendInfo.friendHeadImage = userInfo.headImageThumb; |
|||
friendInfo.friendNickName = userInfo.nickName; |
|||
this.$http({ |
|||
url: "/api/friend/update", |
|||
method: "put", |
|||
data: friendInfo |
|||
}).then(() => { |
|||
this.$store.commit("updateFriend", friendInfo); |
|||
this.$store.commit("setChatUserInfo", userInfo); |
|||
}) |
|||
} |
|||
} |
|||
|
|||
} |
|||
</script> |
|||
|
|||
<style scoped lang="scss"> |
|||
.el-container { |
|||
.l-friend-box { |
|||
border: #dddddd solid 1px; |
|||
background: #eeeeee; |
|||
|
|||
.l-friend-header { |
|||
display: flex; |
|||
align-items: center; |
|||
padding: 5px; |
|||
background-color: white; |
|||
|
|||
.l-friend-search{ |
|||
flex: 1; |
|||
} |
|||
} |
|||
|
|||
.el-main { |
|||
padding: 0; |
|||
} |
|||
} |
|||
|
|||
|
|||
.r-friend-box { |
|||
.user-detail { |
|||
width: 100%; |
|||
display: flex; |
|||
padding: 50px 10px 10px 50px; |
|||
text-align: center; |
|||
justify-content: space-around; |
|||
|
|||
.detail-head-image { |
|||
width: 200px; |
|||
height: 200px; |
|||
} |
|||
|
|||
.info-item { |
|||
width: 400px; |
|||
height: 200px; |
|||
background-color: #ffffff; |
|||
} |
|||
|
|||
.description { |
|||
padding: 20px 20px 0px 20px; |
|||
|
|||
} |
|||
} |
|||
|
|||
.btn-group { |
|||
text-align: left !important; |
|||
padding-left: 100px; |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
} |
|||
</style> |
|||
@ -0,0 +1,70 @@ |
|||
<template> |
|||
<el-container class="im-group-box"> |
|||
<el-aside width="250px" class="l-group-box"> |
|||
<el-header class="l-group-header" height="60px"> |
|||
<div class="l-group-search"> |
|||
<el-input width="200px" placeholder="搜索群聊" v-model="searchText"> |
|||
<el-button slot="append" icon="el-icon-search"></el-button> |
|||
</el-input> |
|||
</div> |
|||
<el-button plain icon="el-icon-plus" |
|||
style="border: none; padding: 12px; font-size: 20px;color: black;" |
|||
title="添加好友" @click="handleCreateGroup()"></el-button> |
|||
</el-header> |
|||
<el-main> |
|||
|
|||
</el-main> |
|||
</el-aside> |
|||
<el-container class="r-chat-box"> |
|||
group |
|||
</el-container> |
|||
</el-container> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: "group", |
|||
data() { |
|||
return { |
|||
searchText: "" |
|||
}; |
|||
}, |
|||
methods: { |
|||
handleCreateGroup() { |
|||
this.$prompt('请输入群聊名称', '创建群聊', { |
|||
confirmButtonText: '确定', |
|||
cancelButtonText: '取消', |
|||
inputPattern: /\S/, |
|||
inputErrorMessage: '请输入群聊名称' |
|||
}).then((o) => { |
|||
this.$http({ |
|||
url: `/api/group/create?groupName=${o.value}`, |
|||
method: 'post' |
|||
}).then((groupInfo)=>{ |
|||
console.log(groupInfo); |
|||
}) |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.im-group-box { |
|||
.l-group-box { |
|||
border: #dddddd solid 1px; |
|||
background: #eeeeee; |
|||
|
|||
.l-group-header { |
|||
display: flex; |
|||
align-items: center; |
|||
padding: 5px; |
|||
background-color: white; |
|||
|
|||
.l-group-search{ |
|||
flex: 1; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
Loading…
Reference in new issue