class MainHandler(UserMixin, web.RequestHandler):
def get(self):
if not self.current_user: # 未设定昵称的用户显示login页面
self.render("login.html")
else:
self.render("index.html", username=self.current_user)
def post(self):
username = self.get_body_argument("username") # 用户提交的用户名
self.set_secure_cookie("username", username)
self.render("index.html", username=username)
修改模板,渲染昵称
昵称:{{ username }} <br/>
-
后端
def on_message(self, message): html = f'<div class="msg">{self.current_user} ({self.user_ip}): {message}</div>' html_self = f'<div class="self">{self.current_user} ({self.user_ip}): {message}</div>' for client in clients: # 消息广播 if client is self: # 群发时不发给自己 continue try: client.write_message(html) except websocket.WebSocketClosedError: pass self.write_message(html_self) # 群发后重新发送给自己
-
前端
ws.onmessage = function (event) { let msg = event.data let node = $( msg ) // 接收html node.hide() $("#msg_log").append(node) node.slideDown() }
- 发送当前得在线用户列表
def open(self, *args, **kwargs):
clients.add(self)
message_live = {
"type": 'user',
"html": "".join([f"<li>{client.current_user}</li>" for client in clients])
}
message_sys = {
"type": "sys",
"html": f'<div class="sys">{self.current_user} ({self.user_ip}) 进入了聊天室</div>'
}
for client in clients: # 消息广播
try:
client.write_message(message_sys)
client.write_message(message_live)
except websocket.WebSocketClosedError:
pass
-
为所有得消息添加type
- on_message
- on_close
-
前端根据type 选择消息处理方式
ws.onmessage = function (event) {
let msg = JSON.parse(event.data)
let node = $(msg.html)
let msg_type = msg.type
console.log(msg)
node.hide() //先隐藏
switch (msg_type) {
case 'user': // 在线用户列表
$("#user_list").html(node)
break;
case 'sys': //系统消息
case "chat": // 聊天内容
$("#msg_log").append(node)
break;
default:
}
node.slideDown() //显示html
}
chat_logs = [] # 聊天记录
def open(self, *args, **kwargs):
...
message_chat_logs = {
"type":"chat",
"html": "".join(chat_logs)
}
self.write_message(message_chat_logs) # 发送之前的聊天记录
...
def on_message(self, message):
....
chat_logs.append(message_chat['html']) # 保存聊天记录
settings = {
"cookie_secret": "sd*^%_Nn30NG%*BTq34905y7389vcnvbk,erjtherg",
"template_path": os.path.join(BASE_DIR, "templates"),
"static_path": os.path.join(BASE_DIR, "static"),# 指定模板目录
# todo 其他设置
}
app = web.Application(urls, **settings)
移动后的文件结构
$ tree
.
|-- app.py
|-- static
| |-- chat.js
| |-- jquery.min.js
|-- templates
|-- index.html
|-- login.html
-
在模板中引入css
<link rel="stylesheet" href="{{ static_url('css.css') }}">
-
static下创建css文件
.left { width: 200px; position: absolute; bottom: 15px; } .right { position: absolute; left: 300px; bottom: 15px; width: 400px; } .msg { font-size: 14px; color: #41aaff; } .self { font-size: 14px; color: #34b577 } .sys { font-size: 12px; color: #ff667e; }