Browse Source

uniapp 单人文字聊天、发送图片

master
xsx 3 years ago
parent
commit
f35311c805
  1. 2
      im-platform/src/main/java/com/bx/implatform/service/impl/UserServiceImpl.java
  2. 2
      im-server/src/main/java/com/bx/imserver/netty/tcp/TcpSocketServer.java
  3. 2
      im-server/src/main/java/com/bx/imserver/netty/ws/WebSocketServer.java
  4. 10
      im-ui/src/components/chat/ChatBox.vue
  5. 18
      im-uniapp/App.vue
  6. 60
      im-uniapp/common/request.js
  7. 19
      im-uniapp/components/friend-item/friend-item.vue
  8. 9
      im-uniapp/main.js
  9. 25
      im-uniapp/pages.json
  10. 6
      im-uniapp/pages/chat/chat.vue
  11. 93
      im-uniapp/pages/common/user-info.vue
  12. 178
      im-uniapp/pages/login/login.vue
  13. BIN
      im-uniapp/static/iconfont/iconfont.ttf
  14. 53
      im-uniapp/store/chatStore.js
  15. 5
      im-uniapp/store/friendStore.js
  16. 2
      im-uniapp/store/groupStore.js
  17. 9
      im-uniapp/store/index.js
  18. 7
      im-uniapp/store/userStore.js

2
im-platform/src/main/java/com/bx/implatform/service/impl/UserServiceImpl.java

@ -103,7 +103,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IU
String strJson = JwtUtil.getInfo(refreshToken); String strJson = JwtUtil.getInfo(refreshToken);
Long userId = JwtUtil.getUserId(refreshToken); Long userId = JwtUtil.getUserId(refreshToken);
String accessToken = JwtUtil.sign(userId,strJson,jwtProperties.getAccessTokenExpireIn(),jwtProperties.getAccessTokenSecret()); String accessToken = JwtUtil.sign(userId,strJson,jwtProperties.getAccessTokenExpireIn(),jwtProperties.getAccessTokenSecret());
String newRefreshToken = JwtUtil.sign(userId,strJson,jwtProperties.getAccessTokenExpireIn(),jwtProperties.getAccessTokenSecret()); String newRefreshToken = JwtUtil.sign(userId,strJson,jwtProperties.getRefreshTokenExpireIn(),jwtProperties.getRefreshTokenSecret());
LoginVO vo =new LoginVO(); LoginVO vo =new LoginVO();
vo.setAccessToken(accessToken); vo.setAccessToken(accessToken);
vo.setAccessTokenExpiresIn(jwtProperties.getAccessTokenExpireIn()); vo.setAccessTokenExpiresIn(jwtProperties.getAccessTokenExpireIn());

2
im-server/src/main/java/com/bx/imserver/netty/tcp/TcpSocketServer.java

@ -59,7 +59,7 @@ public class TcpSocketServer implements IMServer {
protected void initChannel(Channel ch) throws Exception { protected void initChannel(Channel ch) throws Exception {
// 获取职责链 // 获取职责链
ChannelPipeline pipeline = ch.pipeline(); ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new IdleStateHandler(15, 0, 0, TimeUnit.SECONDS)); pipeline.addLast(new IdleStateHandler(30, 0, 0, TimeUnit.SECONDS));
pipeline.addLast("encode",new MessageProtocolEncoder()); pipeline.addLast("encode",new MessageProtocolEncoder());
pipeline.addLast("decode",new MessageProtocolDecoder()); pipeline.addLast("decode",new MessageProtocolDecoder());
pipeline.addLast("handler", new IMChannelHandler()); pipeline.addLast("handler", new IMChannelHandler());

2
im-server/src/main/java/com/bx/imserver/netty/ws/WebSocketServer.java

@ -63,7 +63,7 @@ public class WebSocketServer implements IMServer {
protected void initChannel(Channel ch) throws Exception { protected void initChannel(Channel ch) throws Exception {
// 获取职责链 // 获取职责链
ChannelPipeline pipeline = ch.pipeline(); ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new IdleStateHandler(15, 0, 0, TimeUnit.SECONDS)); pipeline.addLast(new IdleStateHandler(30, 0, 0, TimeUnit.SECONDS));
pipeline.addLast("http-codec", new HttpServerCodec()); pipeline.addLast("http-codec", new HttpServerCodec());
pipeline.addLast("aggregator", new HttpObjectAggregator(65535)); pipeline.addLast("aggregator", new HttpObjectAggregator(65535));
pipeline.addLast("http-chunked", new ChunkedWriteHandler()); pipeline.addLast("http-chunked", new ChunkedWriteHandler());

10
im-ui/src/components/chat/ChatBox.vue

@ -134,7 +134,7 @@
loadStatus: "loading" loadStatus: "loading"
} }
// id // id
this.setTargetId(msgInfo, this.chat.targetId); this.fillTargetId(msgInfo, this.chat.targetId);
// //
this.$store.commit("insertMessage", msgInfo); this.$store.commit("insertMessage", msgInfo);
// //
@ -182,7 +182,7 @@
loadStatus: "loading" loadStatus: "loading"
} }
// id // id
this.setTargetId(msgInfo, this.chat.targetId); this.fillTargetId(msgInfo, this.chat.targetId);
// //
this.$store.commit("insertMessage", msgInfo); this.$store.commit("insertMessage", msgInfo);
// //
@ -232,7 +232,7 @@
type: 3 type: 3
} }
// id // id
this.setTargetId(msgInfo, this.chat.targetId); this.fillTargetId(msgInfo, this.chat.targetId);
this.$http({ this.$http({
url: this.messageAction, url: this.messageAction,
method: 'post', method: 'post',
@ -252,7 +252,7 @@
this.showVoice = false; this.showVoice = false;
}) })
}, },
setTargetId(msgInfo, targetId) { fillTargetId(msgInfo, targetId) {
if (this.chat.type == "GROUP") { if (this.chat.type == "GROUP") {
msgInfo.groupId = targetId; msgInfo.groupId = targetId;
} else { } else {
@ -269,7 +269,7 @@
type: 0 type: 0
} }
// id // id
this.setTargetId(msgInfo, this.chat.targetId); this.fillTargetId(msgInfo, this.chat.targetId);
this.lockMessage = true; this.lockMessage = true;
this.$http({ this.$http({
url: this.messageAction, url: this.messageAction,

18
im-uniapp/App.vue

@ -1,16 +1,18 @@
<script> <script>
export default { export default {
onLaunch: function() { onLaunch() {
console.log('App Launch') //
}, console.log("onLaunch")
onShow: function() { // #ifdef H5
console.log('App Show') //
}, uni.navigateTo({
onHide: function() { url:"/pages/login/login"
console.log('App Hide') })
// #endif
} }
} }
</script> </script>
<style lang="scss"> <style lang="scss">
@import url('./static/icon/iconfont.css');
</style> </style>

60
im-uniapp/common/request.js

@ -1,14 +1,14 @@
const BASE_URL = "http://192.168.43.6:8888"
const request = (options) => { const request = (options) => {
const header = options.header||{}; const header = options.header||{};
const accessToken = uni.getStorageSync("accessToken"); const loginInfo = uni.getStorageSync("loginInfo");
if (accessToken) { if (loginInfo) {
header.accessToken = accessToken; header.accessToken = loginInfo.accessToken;
} }
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
uni.request({ uni.request({
url: BASE_URL + options.url, url: process.env.BASE_URL + options.url,
method: options.method || 'GET', method: options.method || 'GET',
header: header, header: header,
data: options.data || {}, data: options.data || {},
@ -21,8 +21,7 @@ const request = (options) => {
}); });
} else if (res.data.code == 401) { } else if (res.data.code == 401) {
console.log("token失效,尝试重新获取") console.log("token失效,尝试重新获取")
const refreshToken = uni.getStorageSync("refreshToken"); if (!loginInfo) {
if (!refreshToken) {
uni.navigateTo({ uni.navigateTo({
url: '/pages/login/login' url: '/pages/login/login'
}); });
@ -32,7 +31,7 @@ const request = (options) => {
method: 'PUT', method: 'PUT',
url: '/refreshToken', url: '/refreshToken',
header: { header: {
refreshToken: refreshToken refreshToken: loginInfo.refreshToken
} }
}) })
// 换取token失败,跳转至登录界面 // 换取token失败,跳转至登录界面
@ -42,10 +41,7 @@ const request = (options) => {
}); });
} }
// 保存token // 保存token
uni.setStorageSync("accessToken", data.accessToken); uni.setStorageSync("loginInfo", data);
uni.setStorageSync("refreshToken", data.refreshToken);
// 这里需要把headers清掉,否则请求时会报错,原因暂不详...
//response.config.headers=undefined;
// 重新发送刚才的请求 // 重新发送刚才的请求
return request(options) return request(options)
} else { } else {
@ -58,44 +54,6 @@ const request = (options) => {
} }
}, },
fail(error) { fail(error) {
switch (error.response.status) {
case 400:
uni.showToast({
title: error.response.data,
type: 'error',
duration: 1500,
})
break
case 401:
uni.navigateTo({
url: '/pages/login/login'
});
break
case 405:
uni.showToast({
title: 'http请求方式有误',
icon: 'error',
duration: 1500
})
break
case 404:
case 500:
uni.showToast({
title: '服务器出了点小差,请稍后再试',
icon: 'error',
duration: 1500
})
break
case 501:
uni.showToast({
title: '服务器不支持当前请求所需要的某个功能',
icon: 'error',
duration: 1500
})
break
}
return reject(error) return reject(error)
} }
}); });

19
im-uniapp/components/friend-item/friend-item.vue

@ -12,13 +12,12 @@
<script> <script>
export default { export default {
name: "frinedItem", name: "frined-item",
data() { data() {
return {} return {}
}, },
methods:{ methods:{
showFriendInfo(id){ showFriendInfo(){
console.log(id);
uni.navigateTo({ uni.navigateTo({
url: "/pages/common/user-info?id="+this.friend.id url: "/pages/common/user-info?id="+this.friend.id
}) })
@ -42,7 +41,7 @@
<style scope lang="scss"> <style scope lang="scss">
.friend-item { .friend-item {
height: 100rpx; height: 120rpx;
display: flex; display: flex;
margin-bottom: 1rpx; margin-bottom: 1rpx;
position: relative; position: relative;
@ -59,8 +58,8 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
width: 80rpx; width: 100rpx;
height: 80rpx; height: 100rpx;
.head-image{ .head-image{
width: 100%; width: 100%;
@ -70,7 +69,7 @@
} }
.text { .text {
font-size: 30rpx; font-size: 36rpx;
margin-left: 30rpx; margin-left: 30rpx;
flex: 1; flex: 1;
display: flex; display: flex;
@ -80,13 +79,9 @@
flex-shrink: 0; flex-shrink: 0;
overflow: hidden; overflow: hidden;
&>view {
display: flex;
justify-content: flex-start;
}
.online-status { .online-status {
font-size: 22rpx; font-size: 28rpx;
font-weight: 600; font-weight: 600;
&.online { &.online {

9
im-uniapp/main.js

@ -1,12 +1,19 @@
import App from './App' import App from './App'
import request from './common/request'; import request from './common/request';
import emotion from './common/emotion.js';
import * as enums from './common/enums.js';
import * as socketApi from './common/wssocket';
import store from './store'; import store from './store';
import { createSSRApp } from 'vue' import { createSSRApp } from 'vue'
export function createApp() { export function createApp() {
const app = createSSRApp(App) const app = createSSRApp(App)
app.use(store); app.use(store);
app.config.globalProperties.$http = request app.config.globalProperties.$http = request;
app.config.globalProperties.$wsApi = socketApi;
app.config.globalProperties.$emo = emotion;
app.config.globalProperties.$enums = enums;
return { return {
app app
} }

25
im-uniapp/pages.json

@ -7,23 +7,7 @@
}, { }, {
"path": "pages/chat/chat", "path": "pages/chat/chat",
"style": { "style": {
"navigationBarTitleText": "聊天消息", "navigationBarTitleText": "聊天消息"
"app-plus": {
"titleNView": {
"buttons": [{
"text": "&#xe6e0;",
"fontSrc": "/static/iconfont/iconfont.ttf",
"fontSize": "40rpx"
},
{
"text": "&#xe648;",
"fontSrc": "/static/iconFont/iconfont.ttf",
"fontSize": "40rpx"
}
]
}
}
} }
}, { }, {
"path": "pages/friend/friend", "path": "pages/friend/friend",
@ -34,13 +18,13 @@
"titleNView": { "titleNView": {
"buttons": [{ "buttons": [{
"text": "&#xe6e0;", "text": "&#xe6e0;",
"fontSrc": "/static/iconfont/iconfont.ttf", "fontSrc": "/static/icon/iconfont.ttf",
"fontSize": "40rpx", "fontSize": "40rpx",
"width": "50rpx" "width": "50rpx"
}, },
{ {
"text": "&#xe648;", "text": "&#xe648;",
"fontSrc": "/static/iconFont/iconfont.ttf", "fontSrc": "/static/icon/iconfont.ttf",
"fontSize": "30rpx", "fontSize": "30rpx",
"width": "50rpx" "width": "50rpx"
} }
@ -48,7 +32,6 @@
} }
} }
} }
}, { }, {
"path": "pages/group/group", "path": "pages/group/group",
"style": { "style": {
@ -87,6 +70,8 @@
} }
},{ },{
"path": "pages/common/user-info" "path": "pages/common/user-info"
},{
"path": "pages/chat/chat-box"
}], }],
"globalStyle": { "globalStyle": {
"navigationBarTextStyle": "black", "navigationBarTextStyle": "black",

6
im-uniapp/pages/chat/chat.vue

@ -1,6 +1,10 @@
<template> <template>
<view> <view>
消息 <scroll-view class="scroll-bar" scroll-with-animation="true" scroll-y="true">
<view v-for="(chat,index) in $store.state.chatStore.chats" :key="index">
<chat-item :chat="chat" :index="index"></chat-item>
</view>
</scroll-view>
</view> </view>
</template> </template>

93
im-uniapp/pages/common/user-info.vue

@ -2,17 +2,19 @@
<view class="user-info"> <view class="user-info">
<view class="content"> <view class="content">
<view class="avatar"> <view class="avatar">
<image class="head-image" :src="userInfo.headImage" lazy-load="true" mode="aspectFill"></image> <image class="head-image" :src="userInfo.headImage" lazy-load="true" mode="aspectFill"></image>
</view> </view>
<view class="info-item"> <view class="info-item">
<view class="info-primary"> <view class="info-primary">
<text class="info-username"> <text class="info-username">
{{userInfo.userName}} {{userInfo.userName}}
</text> </text>
<uni-icons v-show="userInfo.sex==0" class="sex-boy" type="person-filled" size="20" color="darkblue" ></uni-icons> <uni-icons v-show="userInfo.sex==0" class="sex-boy" type="person-filled" size="20"
<uni-icons v-show="userInfo.sex==1" class="sex-girl" type="person-filled" size="20" color="darkred" ></uni-icons> color="darkblue"></uni-icons>
<uni-icons v-show="userInfo.sex==1" class="sex-girl" type="person-filled" size="20"
color="darkred"></uni-icons>
</view> </view>
<text > <text>
昵称 {{userInfo.nickName}} 昵称 {{userInfo.nickName}}
</text> </text>
<text class="person-wx-name"> <text class="person-wx-name">
@ -22,21 +24,53 @@
</view> </view>
<view class="line"></view> <view class="line"></view>
<view class="btn-group"> <view class="btn-group">
<button v-show="isFriend" type="primary">发消息</button> <button v-show="isFriend" type="primary" @click="sendMessage()">发消息</button>
<button v-show="!isFriend" type="primary">加为好友</button> <button v-show="!isFriend" type="primary" @click="addFriend()">加为好友</button>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
export default{ export default {
data(){ data() {
return { return {
userInfo:{} userInfo: {}
}
},
methods: {
sendMessage() {
let chat = {
type: 'PRIVATE',
targetId: this.userInfo.id,
showName: this.userInfo.nickName,
headImage: this.userInfo.headImage,
};
this.$store.commit("openChat", chat);
uni.switchTab({
url:"/pages/chat/chat"
})
},
addFriend() {
this.$http({
url: "/friend/add?friendId=" + this.userInfo.id,
method: "POST"
}).then((data) => {
let friend = {
id: this.userInfo.id,
nickName: this.userInfo.nickName,
headImage: this.userInfo.headImageThumb,
online: this.userInfo.online
}
this.$store.commit("addFriend", friend);
uni.showToast({
title: '添加成功,对方已成为您的好友',
icon: 'none'
})
})
} }
}, },
computed: { computed: {
isFriend(){ isFriend() {
let friends = this.$store.state.friendStore.friends; let friends = this.$store.state.friendStore.friends;
let friend = friends.find((f) => f.id == this.userInfo.id); let friend = friends.find((f) => f.id == this.userInfo.id);
return friend != undefined; return friend != undefined;
@ -44,64 +78,63 @@
}, },
onLoad(options) { onLoad(options) {
// //
console.log(options.id)
const id = options.id; const id = options.id;
this.$http({ this.$http({
url:"/user/find/"+id url: "/user/find/" + id
}).then((userInfo)=>{ }).then((userInfo) => {
this.userInfo = userInfo; this.userInfo = userInfo;
}) })
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.user-info{ .user-info {
.content{ .content {
height: 200rpx; height: 200rpx;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
padding: 20rpx; padding: 20rpx;
.avatar{
.avatar {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
width: 160rpx; width: 160rpx;
height: 160rpx; height: 160rpx;
.head-image{ .head-image {
width: 100%; width: 100%;
height: 100%; height: 100%;
border-radius: 10%; border-radius: 10%;
} }
} }
.info-item{ .info-item {
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;
flex-direction: column; flex-direction: column;
padding-left: 40rpx; padding-left: 40rpx;
flex: 1; flex: 1;
.info-primary{
.info-primary {
display: flex; display: flex;
.info-username{
.info-username {
font-size: 40rpx; font-size: 40rpx;
font-weight: 600; font-weight: 600;
} }
} }
} }
} }
.line{ .line {
margin: 20rpx; margin: 20rpx;
border-bottom: 1px solid #aaaaaa; border-bottom: 1px solid #aaaaaa;
} }
.btn-group{
.btn-group {
margin: 100rpx; margin: 100rpx;
} }
} }

178
im-uniapp/pages/login/login.vue

@ -3,15 +3,14 @@
<view class="login-title">欢迎登录</view> <view class="login-title">欢迎登录</view>
<uni-forms style="margin-top: 100px;" :modelValue="loginForm" :rules="rules" validate-trigger="bind"> <uni-forms style="margin-top: 100px;" :modelValue="loginForm" :rules="rules" validate-trigger="bind">
<uni-forms-item name="userName"> <uni-forms-item name="userName">
<uni-easyinput type="text" v-model="loginForm.userName" prefix-icon="person" focus <uni-easyinput type="text" v-model="loginForm.userName" prefix-icon="person" focus placeholder="用户名" />
placeholder="用户名" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item name="password"> <uni-forms-item name="password">
<uni-easyinput type="password" v-model="loginForm.password" prefix-icon="locked" placeholder="密码" /> <uni-easyinput type="password" v-model="loginForm.password" prefix-icon="locked" placeholder="密码" />
</uni-forms-item> </uni-forms-item>
<button @click="submit" type="primary">登录</button> <button @click="submit" type="primary">登录</button>
</uni-forms> </uni-forms>
</view> </view>
</template> </template>
@ -39,9 +38,6 @@
} }
} }
} }
},
onLoad() {
}, },
methods: { methods: {
submit() { submit() {
@ -49,18 +45,170 @@
url: '/login', url: '/login',
data: this.loginForm, data: this.loginForm,
method: 'POST' method: 'POST'
}).then( data=>{ }).then(data => {
console.log("登录成功,自动跳转到聊天页面...")
uni.setStorageSync("accessToken", data.accessToken); uni.setStorageSync("loginInfo", data);
uni.setStorageSync("refreshToken", data.refreshToken); this.init(data);
this.$store.dispatch("initStore").then(()=>{ })
console.log("登录成功,准备跳转...") },
uni.switchTab({ init(loginInfo) {
url:"/pages/chat/chat" //
this.$store.dispatch("load").then(() => {
// websocket
this.initWebSocket(loginInfo);
}).catch((e) => {
console.log(e);
this.quit();
})
//
uni.switchTab({
url: "/pages/chat/chat"
})
},
initWebSocket(loginInfo) {
let userId = this.$store.state.userStore.userInfo.id;
this.$wsApi.createWebSocket(process.env.WS_URL, loginInfo.accessToken);
this.$wsApi.onopen(() => {
this.pullUnreadMessage();
});
this.$wsApi.onmessage((cmd, msgInfo) => {
if (cmd == 2) {
// 线
uni.showModal({
content: '您已在其他地方登陆,将被强制下线',
showCancel: false,
}) })
this.quit();
} else if (cmd == 3) {
//
msgInfo.selfSend = userId == msgInfo.sendId;
//
this.handlePrivateMessage(msgInfo);
} else if (cmd == 4) {
//
msgInfo.selfSend = userId == msgInfo.sendId;
//
this.handleGroupMessage(msgInfo);
}
})
},
pullUnreadMessage() {
//
this.$http({
url: "/message/private/pullUnreadMessage",
method: 'POST'
});
//
this.$http({
url: "/message/group/pullUnreadMessage",
method: 'POST'
});
},
handlePrivateMessage(msg) {
//
let friendId = msg.selfSend ? msg.recvId : msg.sendId;
let friend = this.$store.state.friendStore.friends.find((f) => f.id == friendId);
if (!friend) {
//
this.$http({
url: `/friend/find/${msg.sendId}`,
method: 'get'
}).then((friend) => {
this.insertPrivateMessage(friend, msg);
this.$store.commit("addFriend", friend);
}) })
} else {
this.insertPrivateMessage(friend, msg);
}
},
insertPrivateMessage(friend, msg) {
// webrtc
if (msg.type >= this.$enums.MESSAGE_TYPE.RTC_CALL &&
msg.type <= this.$enums.MESSAGE_TYPE.RTC_CANDIDATE) {
// //
// if (msg.type == this.$enums.MESSAGE_TYPE.RTC_CALL ||
// msg.type == this.$enums.MESSAGE_TYPE.RTC_CANCEL) {
// this.$store.commit("showVideoAcceptorBox", friend);
// this.$refs.videoAcceptor.handleMessage(msg)
// } else {
// this.$refs.videoAcceptor.close()
// this.$refs.privateVideo.handleMessage(msg)
// }
// return;
}
let chatInfo = {
type: 'PRIVATE',
targetId: friend.id,
showName: friend.nickName,
headImage: friend.headImage
};
//
this.$store.commit("openChat", chatInfo);
//
this.$store.commit("insertMessage", msg);
//
!msg.selfSend && this.playAudioTip();
},
handleGroupMessage(msg) {
//
let group = this.$store.state.groupStore.groups.find((g) => g.id == msg.groupId);
if (!group) {
//
this.$http({
url: `/group/find/${msg.groupId}`,
method: 'get'
}).then((group) => {
this.insertGroupMessage(group, msg);
this.$store.commit("addGroup", group);
})
} else {
this.insertGroupMessage(group, msg);
}
},
insertGroupMessage(group, msg) {
let chatInfo = {
type: 'GROUP',
targetId: group.id,
showName: group.remark,
headImage: group.headImageThumb
};
//
this.$store.commit("openChat", chatInfo);
//
this.$store.commit("insertMessage", msg);
//
!msg.selfSend && this.playAudioTip();
},
quit() {
uni.showToast({
title: "退出登录"
}) })
console.log("退出登录")
this.$wsApi.closeWebSocket();
uni.removeStorageSync("loginInfo");
uni.navigateTo({
url:"/pages/login/login"
})
},
playAudioTip() {
let audio = new Audio();
let url = "/static/audio/tip.wav";
audio.src = url;
audio.play();
}
},
mounted() {
console.log("login mounted")
let loginInfo = uni.getStorageSync("loginInfo");
if (loginInfo) {
// ,
this.init(loginInfo);
} }
} }
} }

BIN
im-uniapp/static/iconfont/iconfont.ttf

Binary file not shown.

53
im-uniapp/store/chatStore.js

@ -1,15 +1,16 @@
export default { export default {
state: { state: {
activeIndex: -1,
chats: [] chats: []
}, },
mutations: { mutations: {
setChats(state,chats){
console.log(chats);
state.chats = chats;
},
openChat(state, chatInfo) { openChat(state, chatInfo) {
let chat = null; let chat = null;
let activeChat = state.activeIndex>=0?state.chats[state.activeIndex]:null;
for (let i in state.chats) { for (let i in state.chats) {
if (state.chats[i].type == chatInfo.type && if (state.chats[i].type == chatInfo.type &&
state.chats[i].targetId === chatInfo.targetId) { state.chats[i].targetId === chatInfo.targetId) {
@ -34,25 +35,11 @@ export default {
}; };
state.chats.unshift(chat); state.chats.unshift(chat);
} }
// 选中会话保持不变 uni.setStorageSync("chats",state.chats);
if(activeChat){
state.chats.forEach((chat,idx)=>{
if(activeChat.type == chat.type
&& activeChat.targetId == chat.targetId){
state.activeIndex = idx;
}
})
}
},
activeChat(state, idx) {
state.activeIndex = idx;
state.chats[idx].unreadCount = 0;
}, },
removeChat(state, idx) { removeChat(state, idx) {
state.chats.splice(idx, 1); state.chats.splice(idx, 1);
if (state.activeIndex >= state.chats.length) { uni.setStorageSync("chats",state.chats);
state.activeIndex = state.chats.length - 1;
}
}, },
removeGroupChat(state, groupId) { removeGroupChat(state, groupId) {
for (let idx in state.chats) { for (let idx in state.chats) {
@ -113,6 +100,7 @@ export default {
} }
// 新的消息 // 新的消息
chat.messages.push(msgInfo); chat.messages.push(msgInfo);
uni.setStorageSync("chats",state.chats);
}, },
deleteMessage(state, msgInfo){ deleteMessage(state, msgInfo){
@ -141,6 +129,7 @@ export default {
break; break;
} }
} }
uni.setStorageSync("chats",state.chats);
}, },
updateChatFromFriend(state, friend) { updateChatFromFriend(state, friend) {
for (let i in state.chats) { for (let i in state.chats) {
@ -151,6 +140,7 @@ export default {
break; break;
} }
} }
uni.setStorageSync("chats",state.chats);
}, },
updateChatFromGroup(state, group) { updateChatFromGroup(state, group) {
for (let i in state.chats) { for (let i in state.chats) {
@ -161,11 +151,26 @@ export default {
break; break;
} }
} }
}, uni.setStorageSync("chats",state.chats);
resetChatStore(state) {
state.activeIndex = -1;
state.chats = [];
} }
}, },
actions:{
loadChat(context) {
return new Promise((resolve, reject) => {
console.log(".....")
uni.getStorage({
key:"chats",
success(res) {
context.commit("setChats",res.data);
resolve()
},
fail() {
resolve();
}
});
})
}
}
} }

5
im-uniapp/store/friendStore.js

@ -62,7 +62,7 @@ export default {
} }
}, },
actions: { actions: {
initFriendStore(context) { loadFriend(context) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
request({ request({
url: '/friend/list', url: '/friend/list',
@ -71,15 +71,12 @@ export default {
context.commit("setFriends", friends); context.commit("setFriends", friends);
context.dispatch("refreshOnlineStatus"); context.dispatch("refreshOnlineStatus");
resolve() resolve()
console.log("friendstore")
}).catch((res) => { }).catch((res) => {
reject(); reject();
console.log("friendstore reject")
}) })
}); });
}, },
refreshOnlineStatus(context) { refreshOnlineStatus(context) {
console.log(context.state.friends)
if (context.state.friends.length > 0 ) { if (context.state.friends.length > 0 ) {
let userIds = []; let userIds = [];
context.state.friends.forEach((f) => { context.state.friends.forEach((f) => {

2
im-uniapp/store/groupStore.js

@ -37,7 +37,7 @@ export default {
} }
}, },
actions: { actions: {
initGroupStore(context) { loadGroup(context) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
request({ request({
url: '/group/list', url: '/group/list',

9
im-uniapp/store/index.js

@ -14,11 +14,12 @@ const store = createStore({
}, },
state: {}, state: {},
actions: { actions: {
initStore(context) { load(context) {
const promises = []; const promises = [];
promises.push(this.dispatch("initUserStore")); promises.push(this.dispatch("loadUser"));
promises.push(this.dispatch("initFriendStore")); promises.push(this.dispatch("loadFriend"));
promises.push(this.dispatch("initGroupStore")); promises.push(this.dispatch("loadGroup"));
promises.push(this.dispatch("loadChat"));
return Promise.all(promises); return Promise.all(promises);
} }
}, },

7
im-uniapp/store/userStore.js

@ -11,11 +11,6 @@ export default {
mutations: { mutations: {
setUserInfo(state, userInfo) { setUserInfo(state, userInfo) {
// 切换用户后,清理缓存
if(userInfo.id != state.userInfo.id){
console.log("用户切换")
this.commit("resetChatStore");
}
state.userInfo = userInfo; state.userInfo = userInfo;
}, },
setUserState(state, userState) { setUserState(state, userState) {
@ -23,7 +18,7 @@ export default {
}, },
}, },
actions:{ actions:{
initUserStore(context){ loadUser(context){
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
request({ request({
url: '/user/self', url: '/user/self',

Loading…
Cancel
Save