Browse Source

uniapp 群聊功能(未完成)

master
xsx 3 years ago
parent
commit
cc556a9f6f
  1. 4
      im-platform/src/main/java/com/bx/implatform/service/impl/GroupServiceImpl.java
  2. 8
      im-uniapp/package.json
  3. 4
      im-uniapp/pages.json
  4. 97
      im-uniapp/pages/friend/friend-add.vue
  5. 146
      im-uniapp/pages/group/group-edit.vue
  6. 283
      im-uniapp/pages/group/group-info.vue
  7. 130
      im-uniapp/pages/group/group-invite.vue
  8. 105
      im-uniapp/pages/group/group-member.vue

4
im-platform/src/main/java/com/bx/implatform/service/impl/GroupServiceImpl.java

@ -130,7 +130,7 @@ public class GroupServiceImpl extends ServiceImpl<GroupMapper, Group> implements
public void deleteGroup(Long groupId) {
UserSession session = SessionContext.getSession();
Group group = this.getById(groupId);
if(group.getOwnerId().equals(session.getUserId())){
if(!group.getOwnerId().equals(session.getUserId())){
throw new GlobalException(ResultCode.PROGRAM_ERROR,"只有群主才有权限解除群聊");
}
// 逻辑删除群数据
@ -170,7 +170,7 @@ public class GroupServiceImpl extends ServiceImpl<GroupMapper, Group> implements
public void kickGroup(Long groupId, Long userId) {
UserSession session = SessionContext.getSession();
Group group = this.getById(groupId);
if(group.getOwnerId().equals(session.getUserId()) ){
if(!group.getOwnerId().equals(session.getUserId()) ){
throw new GlobalException(ResultCode.PROGRAM_ERROR,"您不是群主,没有权限踢人");
}
if(userId.equals(session.getUserId())){

8
im-uniapp/package.json

@ -6,16 +6,16 @@
"browser":"chrome",
"env": {
"UNI_PLATFORM": "h5",
"BASE_URL": "http://192.168.43.6:8888",
"WS_URL": "ws://192.168.43.6:8878/im"
"BASE_URL": "http://127.0.0.1:8888",
"WS_URL": "ws://127.0.0.1:8878/im"
}
},
"dev-wx-mini": {
"title": "开发环境-微信小程序",
"env": {
"UNI_PLATFORM": "mp-weixin",
"BASE_URL": "http://192.168.43.6:8888",
"WS_URL": "ws://192.168.43.6:8878/im"
"BASE_URL": "http://127.0.0.1:8888",
"WS_URL": "ws://127.0.0.1:8878/im"
}
},
"prod-h5": {

4
im-uniapp/pages.json

@ -40,6 +40,10 @@
"path": "pages/group/group-info"
}, {
"path": "pages/group/group-edit"
}, {
"path": "pages/group/group-invite"
}, {
"path": "pages/group/group-member"
}],
"globalStyle": {
"navigationBarTextStyle": "black",

97
im-uniapp/pages/friend/friend-add.vue

@ -0,0 +1,97 @@
<template>
<view class="page friend-add">
<view class="search-bar">
<uni-search-bar v-model="searchText" :focus="true" @confirm="onSearch()" @cancel="onCancel()"
placeholder="用户名/昵称"></uni-search-bar>
</view>
<view class="user-items">
<scroll-view class="scroll-bar" scroll-with-animation="true" scroll-y="true">
<view v-for="(user) in users" :key="user.id" v-show="user.id != $store.state.userStore.userInfo.id">
<uni-list-chat :avatar="user.headImage" :title="user.userName" :note="'昵称:'+user.nickName"
:clickable="true" @click="onShowUserInfo(user)">
<view class="chat-custom-right">
<button type="primary" v-show="!isFriend(user.id)" size="mini"
@click.stop="onAddFriend(user)">加为好友</button>
<button type="default" v-show="isFriend(user.id)" size="mini" disabled>已添加</button>
</view>
</uni-list-chat>
</view>
</scroll-view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
searchText: "",
users: []
}
},
methods: {
onCancel() {
uni.navigateBack();
},
onSearch() {
console.log("onSearch")
this.$http({
url: "/user/findByName?name=" + this.searchText,
method: "GET"
}).then((data) => {
this.users = data;
})
},
onAddFriend(user) {
this.$http({
url: "/friend/add?friendId=" + user.id,
method: "POST"
}).then((data) => {
let friend = {
id: user.id,
nickName: user.nickName,
headImage: user.headImage,
online: user.online
}
this.$store.commit("addFriend", friend);
uni.showToast({
title: "添加成功,对方已成为您的好友",
icon: "none"
})
})
},
onShowUserInfo(user) {
uni.navigateTo({
url: "/pages/common/user-info?id=" + user.id
})
},
isFriend(userId) {
let friends = this.$store.state.friendStore.friends;
let friend = friends.find((f) => f.id == userId);
return friend != undefined;
}
}
}
</script>
<style scoped lang="scss">
.friend-add {
position: relative;
border: #dddddd solid 1px;
display: flex;
flex-direction: column;
.search-bar {
background: white;
}
.user-items{
position: relative;
flex: 1;
overflow: hidden;
.scroll-bar {
height: 100%;
}
}
}
</style>

146
im-uniapp/pages/group/group-edit.vue

@ -0,0 +1,146 @@
<template>
<view class="page group-edit">
<uni-forms ref="form" :modelValue="group" :rules="rules" validate-trigger="bind" label-position="top"
label-width="100%">
<uni-forms-item label="群聊头像:" name="headImage">
<image-upload :disabled="!isOwner" :onSuccess="onUnloadImageSuccess">
<image :src="group.headImage" class="head-image"></image>
</image-upload>
</uni-forms-item>
<uni-forms-item label="群聊名称:" name="name" :required="true">
<uni-easyinput type="text" v-model="group.name" :disabled="!isOwner" placeholder="请输入群聊名称" />
</uni-forms-item>
<uni-forms-item label="群聊备注:" name="remark">
<uni-easyinput v-model="group.remark" type="text" placeholder="请输入群聊备注" />
</uni-forms-item>
<uni-forms-item label="我在本群的昵称:" name="email">
<uni-easyinput v-model="group.aliasName" type="text" placeholder="请输入群聊昵称" />
</uni-forms-item>
<uni-forms-item label="群公告:" name="notice">
<uni-easyinput type="textarea" v-model="group.notice" :disabled="!isOwner" placeholder="请输入群公告" />
</uni-forms-item>
</uni-forms>
<button type="primary" @click="submit()">提交</button>
</view>
</template>
<script>
export default {
data() {
return {
group: {},
rules: {
name: {
rules: [{
required: true,
errorMessage: '请输入群聊名称',
}]
}
}
}
},
methods: {
submit() {
if (this.group.id) {
this.modifyGroup();
} else {
this.createNewGroup();
}
},
onUnloadImageSuccess(file, res) {
console.log(res)
this.group.headImage = res.data.originUrl;
this.group.headImageThumb = res.data.thumbUrl;
},
modifyGroup() {
this.$http({
url: "/group/modify",
method: "PUT",
data: this.group
}).then((group) => {
this.$store.commit("updateGroup", group);
uni.showToast({
title: "修改群聊信息成功",
icon: 'none'
});
setTimeout(()=>{
uni.navigateBack();
},1000);
})
},
createNewGroup() {
this.$http({
url: "/group/create",
method: 'POST',
data: this.group
}).then((group) => {
this.$store.commit("addGroup", group);
uni.showToast({
title: `群聊创建成功,快邀请小伙伴进群吧`,
icon: 'none',
duration: 2000
});
setTimeout(()=>{
uni.navigateTo({
url: "/pages/group/group-info?id="+group.id
});
},2000)
})
},
loadGroupInfo(id) {
this.$http({
url: `/group/find/${id}`,
method: 'GET'
}).then((group) => {
this.group = group;
//
this.$store.commit("updateChatFromGroup", group);
//
this.$store.commit("updateGroup", group);
});
},
initNewGroup() {
let userInfo = this.$store.state.userStore.userInfo;
this.group = {
name: `${userInfo.userName}创建的群聊`,
headImage: userInfo.headImage,
headImageThumb: userInfo.headImageThumb,
aliasName: userInfo.nickName,
ownerId: this.$store.state.userStore.userInfo.id
}
}
},
computed: {
isOwner() {
return this.$store.state.userStore.userInfo.id == this.group.ownerId
}
},
onLoad(options) {
if (options.id) {
//
this.loadGroupInfo(options.id);
} else {
//
this.initNewGroup();
}
}
}
</script>
<style lang="scss" scoped>
.group-edit {
padding: 20rpx;
.head-image {
width: 200rpx;
height: 200rpx;
}
}
</style>

283
im-uniapp/pages/group/group-info.vue

@ -0,0 +1,283 @@
<template>
<view class="page group-info">
<view class="group-members">
<view class="member-items">
<view v-for="(member,idx) in groupMembers" :key="idx">
<view class="member-item" v-if="idx<9" @click="onShowUserInfo(member.userId)">
<view class="avatar">
<image class="head-image" :src="member.headImage" mode="aspectFill"> </image>
</view>
<view class="text">
<text>{{member.aliasName}}</text>
</view>
</view>
</view>
<view class="invite-btn" @click="onInviteMember()">
<view class="iconfont icon-add-circle"></view>
</view>
</view>
<view class="member-more" @click="onShowMoreMmeber()">查看更多群成员 ></view>
</view>
<view class="group-detail">
<uni-section title="群聊名称:" titleFontSize="30rpx">
<template v-slot:right>
<text>{{group.name}}</text>
</template>
</uni-section>
<uni-section title="群主:" titleFontSize="30rpx">
<template v-slot:right>
<text>{{ownerName}}</text>
</template>
</uni-section>
<uni-section title="群聊备注:" titleFontSize="30rpx">
<template v-slot:right>
<text> {{group.remark}}</text>
</template>
</uni-section>
<uni-section title="我在本群的昵称:" titleFontSize="30rpx">
<template v-slot:right>
<text> {{group.aliasName}}</text>
</template>
</uni-section>
<uni-section title="群公告:" titleFontSize="30rpx">
<uni-notice-bar :text="group.notice" />
</uni-section>
<view class="group-edit" @click="onEditGroup()">修改群聊资料 > </view>
</view>
<view class="btn-group">
<button class="btn" type="primary" @click="onSendMessage()">发消息</button>
<button class="btn" v-show="!isOwner" type="warn" @click="onQuitGroup()">退出群聊</button>
<button class="btn" v-show="isOwner" type="warn" @click="onDissolveGroup()">解散群聊</button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
group: {},
groupMembers: []
}
},
methods: {
onFocusSearch() {},
onInviteMember(){
uni.navigateTo({
url: `/pages/group/group-invite?id=${this.group.id}`
})
},
onShowUserInfo(userId) {
uni.navigateTo({
url: "/pages/common/user-info?id=" + userId
})
},
onShowMoreMmeber(){
uni.navigateTo({
url: `/pages/group/group-member?id=${this.group.id}`
})
},
onEditGroup() {
uni.navigateTo({
url: `/pages/group/group-edit?id=${this.group.id}`
})
},
onSendMessage() {
let chat = {
type: 'GROUP',
targetId: this.group.id,
showName: this.group.remark,
headImage: this.group.headImage,
};
this.$store.commit("openChat", chat);
uni.navigateTo({
url: "/pages/chat/chat-box?chatIdx=0"
})
},
onQuitGroup() {
uni.showModal({
title: '确认退出?',
content: `退出群聊后将不再接受群里的消息,确认退出吗?`,
success: () => {
this.$http({
url: `/group/quit/${this.group.id}`,
method: 'DELETE'
}).then(() => {
this.$store.commit("removeGroup", this.group.id);
this.$store.commit("removeGroupChat", this.group.id);
uni.showModal({
title: `退出成功`,
content: `您已退出群聊'${this.group.name}'`,
showCancel: false,
success:()=>{
uni.navigateBack();
}
})
});
}
});
},
onDissolveGroup() {
uni.showModal({
title: '确认解散?',
content: `确认要解散群聊'${this.group.name}'吗?`,
success:()=>{
this.$http({
url: `/group/delete/${this.group.id}`,
method: 'delete'
}).then(() => {
this.$store.commit("removeGroup", this.group.id);
this.$store.commit("removeGroupChat", this.group.id);
uni.showModal({
title: `解散成功`,
content: `群聊'${this.group.name}'已解散`,
showCancel: false,
success:()=>{
uni.navigateBack();
}
})
});
}
});
},
loadGroupInfo(id) {
this.$http({
url: `/group/find/${id}`,
method: 'GET'
}).then((group) => {
this.group = group;
//
this.$store.commit("updateChatFromGroup", group);
//
this.$store.commit("updateGroup", group);
});
},
loadGroupMembers(id) {
this.$http({
url: `/group/members/${id}`,
method: "GET"
}).then((members) => {
this.groupMembers = members.filter(m => !m.quit);
})
}
},
computed: {
ownerName() {
let member = this.groupMembers.find((m) => m.userId == this.group.ownerId);
return member && member.aliasName;
},
isOwner() {
return this.group.ownerId == this.$store.state.userStore.userInfo.id;
},
},
onLoad(options) {
//
this.loadGroupInfo(options.id);
//
this.loadGroupMembers(options.id)
}
}
</script>
<style lang="scss" scoped>
.group-info {
.group-members {
padding: 30rpx;
background: white;
.member-items {
display: flex;
flex-wrap: wrap;
.member-item {
width: 120rpx;
display: flex;
flex-direction: column;
margin: 8rpx 2rpx;
position: relative;
align-items: center;
padding-right: 5px;
background-color: #fafafa;
white-space: nowrap;
.avatar {
display: flex;
justify-content: center;
align-items: center;
width: 100rpx;
height: 100rpx;
.head-image {
width: 100%;
height: 100%;
border-radius: 10%;
border: #d8d8d8 solid 1px;
}
}
.text {
width: 100%;
flex: 1;
overflow: hidden;
text-align: center;
white-space: nowrap;
}
}
.invite-btn {
display: flex;
justify-content: center;
align-items: center;
width: 100rpx;
height: 100rpx;
margin: 10rpx;
border: #686868 dashed 2px;
border-radius: 10%;
.iconfont {
font-size: 70rpx;
color: #888888;
}
}
}
.member-more {
padding: 20rpx;
text-align: center;
font-size: 30rpx;
}
}
.group-detail {
margin-top: 30rpx;
padding: 30rpx;
background: white;
.group-edit {
padding: 20rpx;
text-align: center;
font-size: 30rpx;
}
}
.btn-group {
margin-top: 30rpx;
padding: 30rpx;
background: white;
.btn {
margin: 10rpx;
}
}
}
</style>

130
im-uniapp/pages/group/group-invite.vue

@ -0,0 +1,130 @@
<template>
<view class="page group-invite">
<view class="search-bar">
<uni-search-bar v-model="searchText" cancelButton="none" placeholder="输入好友昵称搜索"></uni-search-bar>
</view>
<view class="friend-items">
<scroll-view class="scroll-bar" scroll-with-animation="true" scroll-y="true">
<view v-for="friend in friendItems"
v-show="!searchText || friend.nickName.startsWith(searchText)" :key="friend.id">
<uni-list-chat :avatar="friend.headImage" :title="friend.nickName"
:clickable="true" @click="onShowUserInfo(friend.id)">
<view class="chat-custom-right">
<radio :checked="friend.checked" :disabled="friend.disabled" @click.stop="onSwitchChecked(friend)"/>
</view>
</uni-list-chat>
</view>
</scroll-view>
</view>
<view>
<button type="primary" :disabled="inviteSize==0" @click="onInviteFriends()">邀请({{inviteSize}}) </button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
groupId: null,
searchText: "",
groupMembers: [],
friendItems:[]
}
},
methods: {
onInviteFriends(){
let inviteVo = {
groupId: this.groupId,
friendIds: []
}
this.friendItems.forEach((f) => {
if (f.checked && !f.disabled) {
inviteVo.friendIds.push(f.id);
}
})
if (inviteVo.friendIds.length > 0) {
this.$http({
url: "/group/invite",
method: 'POST',
data: inviteVo
}).then(() => {
uni.showToast({
title: "邀请成功",
icon: 'none'
})
setTimeout(()=>{
uni.navigateBack();
},1000);
})
}
},
onShowUserInfo(userId){
uni.navigateTo({
url: "/pages/common/user-info?id=" + userId
})
},
onSwitchChecked(friend){
if(!friend.disabled){
console.log(friend.disabled)
friend.checked = !friend.checked;
}
},
initFriendItems(){
this.friendItems = [];
let friends = this.$store.state.friendStore.friends;
friends.forEach((f=>{
let item = {
id: f.id,
headImage:f.headImage,
nickName: f.nickName,
}
item.disabled = this.isGroupMember(f.id);
item.checked = item.disabled;
this.friendItems.push(item);
}))
},
loadGroupMembers(id) {
this.$http({
url: `/group/members/${id}`,
method: "GET"
}).then((members) => {
this.groupMembers = members.filter(m => !m.quit);
this.initFriendItems();
})
},
isGroupMember(id){
return this.groupMembers.some(m => m.userId==id);
}
},
computed:{
inviteSize(){
return this.friendItems.filter(f => !f.disabled && f.checked).length;
}
},
onLoad(options) {
this.groupId = options.id;
this.loadGroupMembers(options.id);
}
}
</script>
<style lang="scss" scoped>
.group-invite{
position: relative;
border: #dddddd solid 1px;
display: flex;
flex-direction: column;
.friend-items{
position: relative;
flex: 1;
overflow: hidden;
.scroll-bar {
height: 100%;
}
}
}
</style>

105
im-uniapp/pages/group/group-member.vue

@ -0,0 +1,105 @@
<template>
<view class="page group-member">
<view class="search-bar">
<uni-search-bar v-model="searchText" cancelButton="none" placeholder="输入成员昵称搜索"></uni-search-bar>
</view>
<view class="member-items">
<scroll-view class="scroll-bar" scroll-with-animation="true" scroll-y="true">
<view v-for="(member,idx) in groupMembers"
v-show="!searchText || member.aliasName.startsWith(searchText)" :key="idx">
<uni-list-chat :avatar="member.headImage" :title="member.aliasName" :clickable="true"
@click="onShowUserInfo(member.userId)">
<view class="chat-custom-right">
<button type="warn" v-show="isOwner && !isSelf(member.userId)" size="mini"
@click.stop="onKickOut(member,idx)">移出群聊</button>
</view>
</uni-list-chat>
</view>
</scroll-view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
searchText: "",
group: {},
groupMembers: []
}
},
methods: {
onShowUserInfo(userId) {
uni.navigateTo({
url: "/pages/common/user-info?id=" + userId
})
},
onKickOut(member, idx) {
uni.showModal({
title: '确认移出?',
content: `确定将成员'${member.aliasName}'移出群聊吗?`,
success: () => {
this.$http({
url: `/group/kick/${this.group.id}?userId=${member.userId}`,
method: 'DELETE'
}).then(() => {
uni.showToast({
title: `已将${member.aliasName}移出群聊`,
icon: 'none'
})
this.groupMembers.splice(idx, 1);
});
}
})
},
loadGroupInfo(id) {
this.$http({
url: `/group/find/${id}`,
method: 'GET'
}).then((group) => {
this.group = group;
});
},
loadGroupMembers(id) {
this.$http({
url: `/group/members/${id}`,
method: "GET"
}).then((members) => {
this.groupMembers = members.filter(m => !m.quit);
})
},
isSelf(userId) {
return this.$store.state.userStore.userInfo.id == userId
}
},
computed: {
isOwner() {
return this.$store.state.userStore.userInfo.id == this.group.ownerId;
}
},
onLoad(options) {
this.loadGroupInfo(options.id);
this.loadGroupMembers(options.id);
}
}
</script>
<style scoped lang="scss">
.group-invite{
position: relative;
border: #dddddd solid 1px;
display: flex;
flex-direction: column;
.member-items{
position: relative;
flex: 1;
overflow: hidden;
.scroll-bar {
height: 100%;
}
}
}
</style>
Loading…
Cancel
Save