Flask 15行代码自动回复机器人(附vue前端)

最近没事儿看下Flask,相比Django简直小的不要不要的,单个文件几行代码就完成了路由视图,使用websocker与之结合写一个自动回复聊天程序竟然也只用了15行代码。

线上效果图![](https://img.diandian100.cn/20190919151046.png

这个小程序用到了flaskwebsocketwsgi,前端使用了html+css+vue。因为只是演示,所以没考虑使用webpack打包,代码包含简单注释,所以就不再详细解释每行代码了。依次附上代码:

注:本地ip为:10.10.10.238

Flask代码

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
import json

from flask import Flask, request
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer

# 开启一个flask应用
app = Flask(__name__)

# 定义路由和函数功能
@app.route('/msg')
def msg():
# 接收连接用户socket
user_socker = request.environ.get('wsgi.websocket')
# 保持与客户端通信
while 1:
# 接收客户端发来的消息
msg = user_socker.receive()
# 将要返回给客户端的数据封装到一个字典
res = {"id" : 0, "user" : 'https://pic.qqtn.com/up/2018-2/15175580434330335.gif', "msg" : '您刚才发送的消息为:【'+str(msg)+'】'}
# 编码为json格式并发送给客户端
user_socker.send(json.dumps(res))

if __name__ == '__main__':
# 创建一个服务器,IP地址为0.0.0.0,端口是9687,处理函数是app
http_server = WSGIServer(('0.0.0.0', 9687), app, handler_class=WebSocketHandler)
# 开始监听请求:
http_server.serve_forever()

前端代码

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
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>聊天窗口</title>
<style>
/**重置标签默认样式*/
* {
margin: 0;
padding: 0;
list-style: none;
font-family: '微软雅黑'
}

.container {
width: 450px;
height: 780px;
background: #eee;
margin: 80px auto 0;
position: relative;
box-shadow: 20px 20px 55px #777;
}

.header {
background: #000;
height: 40px;
color: #fff;
line-height: 34px;
font-size: 20px;
padding: 0 10px;
}

.footer {
width: 430px;
height: 50px;
background: #666;
position: absolute;
bottom: 0;
padding: 10px;
}

.footer input {
width: 275px;
height: 45px;
outline: none;
font-size: 20px;
text-indent: 10px;
position: absolute;
border-radius: 6px;
right: 80px;
}

.footer span {
display: inline-block;
width: 62px;
height: 48px;
background: #ccc;
font-weight: 900;
line-height: 45px;
cursor: pointer;
text-align: center;
position: absolute;
right: 10px;
border-radius: 6px;
}

.footer span:hover {
color: #fff;
background: #999;
}

#user_face_icon {
display: inline-block;
background: red;
width: 60px;
height: 60px;
border-radius: 30px;
position: absolute;
bottom: 6px;
left: 14px;
cursor: pointer;
overflow: hidden;
}

img {
width: 60px;
height: 60px;
}

.content {
font-size: 20px;
width: 435px;
height: 662px;
overflow: auto;
padding: 5px;
}

.content li {
margin-top: 10px;
padding-left: 10px;
width: 412px;
display: block;
clear: both;
overflow: hidden;
}

.content li img {
float: left;
}

.content li span {
background: #7cfc00;
padding: 10px;
border-radius: 10px;
float: left;
margin: 6px 10px 0 10px;
max-width: 310px;
border: 1px solid #ccc;
box-shadow: 0 0 3px #ccc;
}

.content li img.imgleft {
float: left;
}

.content li img.imgright {
float: right;
}

.content li span.spanleft {
float: left;
background: #fff;
}

.content li span.spanright {
float: right;
background: #7cfc00;
}
</style>
</head>
<body>
<div id="app" class="container">
<div class="header">
<span style="float: left;">与机器人聊天中</span>
<span style="float: right;">14:21</span>
</div>
<ul class="content">
<!-- 循环消息列表 -->
<li v-for="(item,index) in messages_list" v-key="index">
<img v-bind:src="item.user" v-bind:class="{'imgright':item.id}"><span v-bind:class="{'spanright':item.id}">{{item.msg}}</span>
</li>
</ul>
<div class="footer">
<div id="user_face_icon">
<img src="http://www.xttblog.com/icons/favicon.ico" alt="">
</div>
<input id="text" v-model="sends" type="text" placeholder="说点什么吧...">
<span id="btn" v-on:click="sendMessage">发送</span>
</div>
</div>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script>
<script>
// 连接服务器
ws = new WebSocket('ws://10.10.10.238:9687/msg')
// 接收消息
ws.onmessage = function (data) {
// 将服务器每次发来的消息存放在vue实例中
app.messages_list.push(JSON.parse(data.data))
}
// 实例化一个vue对象
var app = new Vue({
el: '#app',
data: {
// 发送给服务器的内容,与发送表单绑定
sends: '',
// 存放服务器与客户端聊天数据
messages_list: []
},
watch: {
// 监听聊天数据,每次有变化将聊天区域滚动条定位到底部
messages_list: function (newQuestion, oldQuestion) {
var content = document.getElementsByTagName('ul')[0];
content.scrollTop = content.scrollHeight;
}
},
methods: {
// 发送给服务端消息
sendMessage: function () {
// 现将要发送的消息存放到聊天数据中心
this.messages_list.push({
id: 1,
user: 'https://pic.qqtn.com/up/2018-2/15175580428030394.gif',
msg: this.sends
})
// 发送给服务器消息
ws.send(this.sends)
// 发送消息后置空发送消息框
this.sends = ''
}
}
})
</script>

</body>
</html>

结束

以上就是完整的前后端代码,使用时将ip改为自己的代码就可以了,注聊天框中服务器与客户端消息显示位置以消息对象中id为表示,id为1代表客户端,0代表服务器。