Skip to content

Commit 2d5c22d

Browse files
committedDec 28, 2021
9th
1 parent b9bd86a commit 2d5c22d

File tree

1 file changed

+396
-1
lines changed

1 file changed

+396
-1
lines changed
 

‎docs/news_rec_sys/task4/README.md

+396-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,121 @@
1010

1111
# 2.前端框架
1212

13-
## 2.1目录结构
13+
## 2.1win10环境开发配置
14+
15+
因为之前玩过django所以历史遗留了一个node v12.8.0 的环境,可是那个项目又没做完
16+
17+
而这个项目是在node v16.13.1 下配置的
18+
19+
所以需要一个node版本管理的软件
20+
21+
请教MoMo
22+
23+
在Mac或者linux下
24+
25+
```bash
26+
#安装n模块
27+
npm install -g n
28+
#升级到最新稳定版
29+
n stable
30+
#安装指定版本
31+
n v6.11.5
32+
```
33+
34+
我自己是win10,在同事的请教下发现win10也有node的版本管理工具nvm-windows
35+
36+
https://github.com/coreybutler/nvm-windows/releases
37+
38+
下载Assets中的nvm-setup.zip
39+
40+
我当前是1.1.9版本,用chrome下载会提示该文件会提示“******文件 存在危险,因此Chrome已将其拦截”,查看全部然后仍要保留就可以了
41+
42+
下完之后要解压是一个exe,双击安装
43+
44+
安装路径设置:nvm路径我是换到了D盘D:\nvm,nodejs软连接(symlink)设置成D:\nvm\nodejs,文件夹名不能带空格,不要带中文!!安装后,电脑会自动配置好系统环境。
45+
46+
然后这个安装过程是不会自动给你生产这个D:\nvm\nodejs文件夹的,我们在nvm文件夹下自己新建一个nodejs文件夹
47+
48+
然后修改settings.txt
49+
50+
```
51+
root: D:\nvm
52+
path: D:\nvm\nodejs
53+
arch: 64
54+
node_mirror: https://npm.taobao.org/mirrors/node/
55+
npm_mirror: https://npm.taobao.org/mirrors/npm/
56+
```
57+
58+
然后!!!
59+
60+
用管理员权限打开cmd
61+
62+
###### 安装node
63+
64+
- nvm install 12.8.0
65+
66+
> 下载成功的时候,会提示你同时下载安装npm对应的版本
67+
68+
- 根据提示,切换到对应的node版本 nvm use 12.8.0
69+
- nvm list 查看当前已安装和使用的node版本,正在使用中的node版本号前面会使用*标识
70+
- node -v 查看node版本
71+
- npm -v 查看npm版本
72+
73+
然后安装python27
74+
75+
https://www.python.org/downloads/release/python-2718/
76+
77+
[Windows x86-64 MSI installer](https://www.python.org/ftp/python/2.7.18/python-2.7.18.amd64.msi)
78+
79+
装完之后记得配环境变量
80+
81+
1. 跳转到前端项目文件目录:`cd Vue-newsinfo`
82+
83+
2. 在本地跑的话,记得打开文件`package.json`,修改第49行的IP和端口,修改内容如下:
84+
85+
```javascript
86+
"scripts": {
87+
"test": "echo \"Error: no test specified\" && exit 1",
88+
"dev": "webpack-dev-server --open --port 8686 --contentBase src --hot --host 127.0.0.1",
89+
"start": "nodemon src/main.js"
90+
},
91+
```
92+
93+
127.0.0.1表示游览器的访问IP(也称为本地IP),8686表示访问端口
94+
95+
3. 修改访问后端API接口的IP和端口,打开文件`main.js`,文件路径:`src/main.js`,修改第23行的IP和端口,修改内容如下:
96+
97+
```javascript
98+
// Vue.prototype.$http = axios
99+
Vue.use(VueAxios, axios);
100+
// axios公共基路径,以后所有的请求都会在前面加上这个路径
101+
axios.defaults.baseURL = "http://39.108.138.91:3000"
102+
//改成后端api的url
103+
```
104+
105+
127.0.0.1表示后端项目的访问IP(也称为本地IP),5000表示访问端口。
106+
107+
4. 设置npm使用py27
108+
109+
```javascript
110+
npm install --python=python2.7
111+
```
112+
113+
或将其设置为始终用于:
114+
115+
```javascript
116+
npm config set python python2.7
117+
(我用的这个,管用!)
118+
```
119+
120+
5. 本地安装node环境,在项目根目录命令行输入命令`npm install`安装依赖包
121+
122+
如果因为版本或者网络问题下载失败请执行`npm install -g cnpm -registry=https://registry.npm.taobao.org/
123+
``cnpm install`
124+
125+
6. 启动前端服务:`npm run dev`
126+
127+
## 2.2目录结构
14128

15129
```
16130
Vue-newsinfo
@@ -44,6 +158,38 @@ Vue-newsinfo
44158
+---webpack.config.js-------------------webpack的配置文件,用于项目打包
45159
```
46160

161+
## 2.3 创建Vue项目的流程
162+
163+
1. 安装Vue CLI:提供基于Vue.js快速开发的工具,可实现交互式的项目脚手架搭建
164+
2. 创建Vue项目:使用`vue create`命令,创建项目
165+
3. 路由配置:使用`vue-router`库,配置`router.js`
166+
4. 数据请求:使用`axios`封装数据请求
167+
5. 选择UI组件库:选择UI设计组件,用于保证界面一致、用户交互、设计简洁的操作流程
168+
169+
## 2.4 页面功能
170+
171+
### 2.4.1 登录/注册页(signIn.vue/signUp.vue)
172+
173+
- 代码位于`src/components/`中的`signIn.vue``signUp.vue`
174+
- 用户登录:输入用户名和密码,登录系统,勾选“记住我”,可以暂存7天的登录信息
175+
- 用户注册:输入用户名、密码、验证密码、年龄,勾选性别和城市,进行用户注册,注册成功之后,将跳转到推荐页
176+
177+
### 2.4.2 推荐/热门页(recLists.vue/hotLists.vue)
178+
179+
- 代码位于`src/components/`中的`recLists.vue``hotLists.vue`
180+
- 推荐页列表:展示用户推荐页新闻列表,一次展示10条数据
181+
- 热门页列表:展示用户热门页新闻列表,一次展示10条数据
182+
183+
### 2.4.3 新闻详情页(NewsInfo.vue)
184+
185+
- 代码位于`src/components/`中的`NewsInfo.vue`
186+
- 新闻详情:展示当前新闻内容,并提供点赞(喜欢)和收藏功能
187+
188+
### 2.4.4 个人中心页(Myself.vue)
189+
190+
- 代码位于`src/components/`中的`Myself.vue`
191+
- 个人中心:展示用户头像和用户名,提供用户退出功能
192+
47193

48194

49195
# 3.后端框架
@@ -68,3 +214,252 @@ news_rec_sys
68214
+--server.py------------------------------------后端项目启动主程序
69215
```
70216

217+
## 3.2后端API接口
218+
219+
### 3.2.1 用户注册请求
220+
221+
- 注册流程:通过前端接收JSON数据(包括用户名、密码、年龄、性别、所在城市),并使用Flask提供用户注册请求服务`/recsys/register`
222+
- 代码逻辑:位于`server.py`中的`register()`方法,接收用户名、密码、年龄、性别、所在城市,根据用户名判断是否已经存在(调用`user_action_controller`中的`user_is_exist()`方法),如果有记录,则返回1,表示注册正常,否则返回0,表示注册失败;再将数据存入MySQL的`userinfo`库的`register_user`表中
223+
224+
```python
225+
@app.route('/recsys/register', methods=["POST"])
226+
def register():
227+
"""用户注册
228+
"""
229+
request_str = request.get_data()
230+
request_dict = json.loads(request_str)
231+
# print(request_dict)
232+
233+
user = RegisterUser()
234+
user.username = request_dict["username"]
235+
user.passwd = request_dict["passwd"]
236+
237+
# 查询当前用户名是否已经被用过了
238+
result = UserAction().user_is_exist(user, "register")
239+
240+
if result != 0:
241+
return jsonify({"code": 500, "mgs": "this username is exists"})
242+
243+
user.userid = snowflake.client.get_guid() # 雪花算法
244+
245+
user.age = request_dict["age"]
246+
user.gender = request_dict["gender"]
247+
user.city = request_dict["city"]
248+
249+
# 检验年龄格式的合法性
250+
try:
251+
age = int(user.age)
252+
except:
253+
return jsonify({"code": 500, "mgs": "age is not valid."})
254+
255+
# 添加注册用户
256+
save_res = UserAction().save_user(user)
257+
if not save_res:
258+
return jsonify({"code": 500, "mgs": "register fail."})
259+
260+
return jsonify({"code": 200, "msg": "register success."})
261+
```
262+
263+
### 3.2.2 用户登录请求
264+
265+
- 登录流程:通过前端接收JSON数据(包括用户名、密码),并使用Flask提供用户登录请求服务`/recsys/login`
266+
- 代码逻辑:位于`server.py`中的`login()`方法,接收用户名、密码,根据用户名和密码判断是否有记录,如果有记录,则返回1,表示登录正常;如果仅用户名存在,返回2,表示密码错误;否则返回0,表示用户不存在
267+
268+
```python
269+
@app.route('/recsys/login', methods=["POST"])
270+
def login():
271+
"""用户登录
272+
"""
273+
request_str = request.get_data()
274+
request_dict = json.loads(request_str)
275+
276+
user = RegisterUser()
277+
user.username = request_dict["username"]
278+
user.passwd = request_dict["passwd"]
279+
280+
# 查询数据库中的用户名或者密码是否存在
281+
try:
282+
result = UserAction().user_is_exist(user, "login")
283+
# print(result,"login")
284+
if result == 1:
285+
return jsonify({"code": 200, "msg": "login success"})
286+
elif result == 2:
287+
# 密码错误
288+
return jsonify({"code": 501, "msg": "passwd is error"})
289+
else:
290+
return jsonify({"code": 502, "msg": "this username is not exist!"})
291+
except Exception as e:
292+
return jsonify({"code": 500, "mgs": "login fail."})
293+
```
294+
295+
### 3.2.3 用户推荐页请求
296+
297+
- 登录流程:通过前端接收json数据(包括用户名、年龄、性别),并使用Flask提供用户推荐页请求服务`/recsys/rec_list`
298+
- 代码逻辑:位于`server.py`中的`rec_list()`方法,接收用户名、年龄、性别,根据用户名得到用户ID,根据用户ID调用冷启动的推荐页列表方法(`recprocess/online.py`中的`get_cold_start_rec_list_v2()`方法),返回10条推荐新闻
299+
300+
```python
301+
@app.route('/recsys/rec_list', methods=["GET"])
302+
def rec_list():
303+
"""推荐页
304+
"""
305+
user_name = request.args.get('user_id')
306+
age = request.args.get('age')
307+
gender = request.args.get('gender')
308+
309+
# 如果年龄无法转int说明是老用户,不需要传age 和 gender
310+
try:
311+
age = int(age)
312+
except:
313+
age = None
314+
gender = None
315+
316+
# 查询用户的id
317+
user_id = UserAction().get_user_id_by_name(user_name)
318+
if not user_id:
319+
return False
320+
321+
if user_id is None:
322+
return jsonify({"code": 2000, "msg": "user_id is none!"})
323+
324+
try:
325+
rec_news_list = recsys_server.get_cold_start_rec_list_v2(user_id, age, gender)
326+
# 冷启动策略
327+
# rec_news_list = recsys_server.get_cold_start_rec_list(user_id)
328+
if len(rec_news_list) == 0:
329+
jsonify({"code": 500, "msg": "rec_news_list is empty."})
330+
return jsonify({"code": 200, "msg": "request rec_list success.", "data": rec_news_list, "user_id": user_id})
331+
except Exception as e:
332+
print(str(e))
333+
return jsonify({"code": 500, "msg": "redis fail."})
334+
```
335+
336+
### 3.2.4 用户热门页请求
337+
338+
- 登录流程:通过前端接收json数据(包括用户名),并使用Flask提供用户热门页请求服务`/recsys/hot_list`
339+
- 代码逻辑:位于`server.py`中的`hot_list()`方法,接收用户名,根据用户名得到用户ID,根据用户ID调用热门页列表方法(`recprocess/online.py`中的`get_hot_list_v2()`方法),返回10条热门新闻
340+
341+
```python
342+
@app.route('/recsys/hot_list', methods=["GET"])
343+
def hot_list():
344+
"""热门页面
345+
"""
346+
user_name = request.args.get('user_id')
347+
348+
if user_name is None:
349+
return jsonify({"code": 2000, "msg": "user_name none!"})
350+
351+
# 查询用户的id
352+
user_id = UserAction().get_user_id_by_name(user_name)
353+
if not user_id:
354+
return jsonify({"code": 2000, "msg": "user_id is not exits!."})
355+
356+
try:
357+
# 这里需要改成get_hot_list, 当前get_hot_list方法还没有实现
358+
# rec_news_list = recsys_server.get_hot_list(user_id)
359+
rec_news_list = recsys_server.get_hot_list_v2(user_id)
360+
if len(rec_news_list) == 0:
361+
return jsonify({"code": 500, "msg": "request redis data fail."})
362+
return jsonify({"code": 200, "msg": "request hot_list success.", "data": rec_news_list, "user_id": user_id})
363+
except Exception as e:
364+
print(str(e))
365+
return jsonify({"code": 2000, "msg": "request hot_list fail."})
366+
```
367+
368+
### 3.2.5 新闻详情请求
369+
370+
- 登录流程:通过前端接收json数据(包括用户名,新闻ID),并使用Flask提供新闻详情请求服务`/recsys/news_detail`
371+
- 代码逻辑:位于`server.py`中的`news_detail()`方法,接收用户名,新闻ID,根据用户名得到用户ID,根据新闻ID得到新闻内容,通过查询`user_likes`表和`user_collections`表,得到新闻的用户行为(是否点赞、是否收藏),返回前端需要的新闻详情(新闻内容、用户是否点赞、用户是否收藏)
372+
373+
```python
374+
@app.route('/recsys/news_detail', methods=["GET"])
375+
def news_detail():
376+
"""一篇文章的详细信息
377+
"""
378+
user_name = request.args.get('user_name')
379+
news_id = request.args.get('news_id')
380+
381+
user_id = UserAction().get_user_id_by_name(user_name)
382+
383+
# if news_id is None or user_id is None:
384+
if news_id is None or user_name is None:
385+
return jsonify({"code": 2000, "msg": "news_id is none or user_name is none!"})
386+
try:
387+
news_detail = recsys_server.get_news_detail(news_id)
388+
389+
# recsys_server.save_user_consume(user_id,news_id) # 记录用户消费的
390+
391+
if UserAction().get_likes_counts_by_user(user_id,news_id) > 0:
392+
news_detail["likes"] = True
393+
else:
394+
news_detail["likes"] = False
395+
396+
if UserAction().get_coll_counts_by_user(user_id,news_id) > 0:
397+
news_detail["collections"] = True
398+
else:
399+
news_detail["collections"] = False
400+
401+
return jsonify({"code": 0, "msg": "request news_detail success.", "data": news_detail})
402+
except Exception as e:
403+
print(str(e))
404+
return jsonify({"code": 2000, "msg": "error"})
405+
```
406+
407+
### 3.2.6 用户行为请求
408+
409+
- 登录流程:通过前端接收json数据(包括用户名,新闻ID、用户行为),并使用Flask提供新闻详情请求服务`/recsys/action`
410+
- 代码逻辑:位于`server.py`中的`actions()`方法,接收用户名,新闻ID、用户行为,根据用户名得到用户ID,根据用户行为(是否点赞、收藏),修改`user_likes`表和`user_collections`表中对应的记录
411+
412+
```python
413+
@app.route('/recsys/action', methods=["POST"])
414+
def actions():
415+
"""用户的行为:阅读,点赞,收藏
416+
"""
417+
request_str = request.get_data()
418+
request_dict = json.loads(request_str)
419+
420+
username = request_dict.get('user_name')
421+
newsid = request_dict.get('news_id')
422+
actiontype = request_dict.get("action_type")
423+
actiontime = request_dict.get("action_time")
424+
425+
userid = UserAction().get_user_id_by_name(username) # 获取用户 id
426+
if not userid:
427+
return jsonify({"code": 2000, "msg": "user not register"})
428+
429+
#TODO 先判断当前的action_type是否是取消的意思,如果是的话,需要将数据库中对应的操作删掉
430+
action_type_list = actiontype.split(":")
431+
# print(actiontype)
432+
if len(action_type_list) == 2:
433+
_action_type = action_type_list[0]
434+
if action_type_list[1] == "false": # 如果数据库中这个参数为false的话
435+
# 删除数据
436+
if _action_type=="likes":
437+
UserAction().del_likes_by_user(userid,newsid) # 删除用户喜欢记录
438+
elif _action_type=="collections":
439+
UserAction().del_coll_by_user(userid,newsid) # 删除用户收藏记录
440+
else:
441+
if _action_type=="likes":
442+
userlikes = UserLikes()
443+
userlikes.new(userid,username,newsid)
444+
UserAction().save_one_action(userlikes) # 记录用户喜欢记录
445+
elif _action_type=="collections":
446+
usercollections = UserCollections()
447+
usercollections.new(userid,username,newsid)
448+
UserAction().save_one_action(usercollections) # 记录用户收藏记录
449+
450+
try:
451+
# 落日志
452+
logitem = LogItem()
453+
logitem.new(userid,newsid,action_type_list[0])
454+
LogController().save_one_log(logitem)
455+
456+
# 更新redis中的展示数据 新闻侧
457+
# if action_type_list[0] in ["read","likes","collections"]:
458+
recsys_server.update_news_dynamic_info(news_id=newsid,action_type=action_type_list)
459+
return jsonify({"code": 200, "msg": "action success"})
460+
461+
except Exception as e:
462+
print(str(e))
463+
return jsonify({"code": 2000, "msg": "action error"})
464+
```
465+

0 commit comments

Comments
 (0)
Please sign in to comment.