-
Notifications
You must be signed in to change notification settings - Fork 201
/
chat.js
222 lines (187 loc) · 5.39 KB
/
chat.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
/**
* @fileOverview 聊天室综合 Demo 示例
*/
// 引入 QCloud 小程序增强 SDK
var qcloud = require('../../vendor/qcloud-weapp-client-sdk/index');
// 引入配置
var config = require('../../config');
/**
* 生成一条聊天室的消息的唯一 ID
*/
function msgUuid() {
if (!msgUuid.next) {
msgUuid.next = 0;
}
return 'msg-' + (++msgUuid.next);
}
/**
* 生成聊天室的系统消息
*/
function createSystemMessage(content) {
return { id: msgUuid(), type: 'system', content };
}
/**
* 生成聊天室的聊天消息
*/
function createUserMessage(content, user, isMe) {
return { id: msgUuid(), type: 'speak', content, user, isMe };
}
// 声明聊天室页面
Page({
/**
* 聊天室使用到的数据,主要是消息集合以及当前输入框的文本
*/
data: {
messages: [],
inputContent: '大家好啊',
lastMessageId: 'none',
},
/**
* 页面渲染完成后,启动聊天室
* */
onReady() {
wx.setNavigationBarTitle({ title: '三木聊天室' });
if (!this.pageReady) {
this.pageReady = true;
this.enter();
}
},
/**
* 后续后台切换回前台的时候,也要重新启动聊天室
*/
onShow() {
if (this.pageReady) {
this.enter();
}
},
/**
* 页面卸载时,退出聊天室
*/
onUnload() {
this.quit();
},
/**
* 页面切换到后台运行时,退出聊天室
*/
onHide() {
this.quit();
},
/**
* 启动聊天室
*/
enter() {
this.pushMessage(createSystemMessage('正在登录...'));
// 如果登录过,会记录当前用户在 this.me 上
if (!this.me) {
qcloud.request({
url: `https://${config.service.host}/user`,
login: true,
success: (response) => {
this.me = response.data.data.userInfo;
this.connect();
}
});
} else {
this.connect();
}
},
/**
* 连接到聊天室信道服务
*/
connect() {
this.amendMessage(createSystemMessage('正在加入群聊...'));
// 创建信道
var tunnel = this.tunnel = new qcloud.Tunnel(config.service.tunnelUrl);
// 连接成功后,去掉「正在加入群聊」的系统提示
tunnel.on('connect', () => this.popMessage());
// 聊天室有人加入或退出,反馈到 UI 上
tunnel.on('people', people => {
const { total, enter, leave } = people;
if (enter) {
this.pushMessage(createSystemMessage(`${enter.nickName}已加入群聊,当前共 ${total} 人`));
} else {
this.pushMessage(createSystemMessage(`${leave.nickName}已退出群聊,当前共 ${total} 人`));
}
});
// 有人说话,创建一条消息
tunnel.on('speak', speak => {
const { word, who } = speak;
this.pushMessage(createUserMessage(word, who, who.openId === this.me.openId));
});
// 信道关闭后,显示退出群聊
tunnel.on('close', () => {
this.pushMessage(createSystemMessage('您已退出群聊'));
});
// 重连提醒
tunnel.on('reconnecting', () => {
this.pushMessage(createSystemMessage('已断线,正在重连...'));
});
tunnel.on('reconnect', () => {
this.amendMessage(createSystemMessage('重连成功'));
});
// 打开信道
tunnel.open();
},
/**
* 退出聊天室
*/
quit() {
if (this.tunnel) {
this.tunnel.close();
}
},
/**
* 通用更新当前消息集合的方法
*/
updateMessages(updater) {
var messages = this.data.messages;
updater(messages);
this.setData({ messages });
// 需要先更新 messagess 数据后再设置滚动位置,否则不能生效
var lastMessageId = messages.length ? messages[messages.length - 1].id : 'none';
this.setData({ lastMessageId });
},
/**
* 追加一条消息
*/
pushMessage(message) {
this.updateMessages(messages => messages.push(message));
},
/**
* 替换上一条消息
*/
amendMessage(message) {
this.updateMessages(messages => messages.splice(-1, 1, message));
},
/**
* 删除上一条消息
*/
popMessage() {
this.updateMessages(messages => messages.pop());
},
/**
* 用户输入的内容改变之后
*/
changeInputContent(e) {
this.setData({ inputContent: e.detail.value });
},
/**
* 点击「发送」按钮,通过信道推送消息到服务器
**/
sendMessage(e) {
// 信道当前不可用
if (!this.tunnel || !this.tunnel.isActive()) {
this.pushMessage(createSystemMessage('您还没有加入群聊,请稍后重试'));
if (this.tunnel.isClosed()) {
this.enter();
}
return;
}
setTimeout(() => {
if (this.data.inputContent && this.tunnel) {
this.tunnel.emit('speak', { word: this.data.inputContent });
this.setData({ inputContent: '' });
}
});
},
});