# personal_blog_project **Repository Path**: zhang-wenyuan0313/personal-blog-project-complete ## Basic Information - **Project Name**: personal_blog_project - **Description**: 个人博客项目 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-05-11 - **Last Updated**: 2022-12-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 第四组—个人博客 # 一、需求分析 ## 1.1 主业务流程 ![img](README.assets/1650865550768-9117beb4-cc86-4d1d-af4f-3648c6cbe168-16522408727446.png) ## 1.2 角色功能分析 ![个人blog项目](README.assets/1652055473328-bd2aa483-cddf-45f6-839e-addd06c376f5-16522408760928.png) ## 1.3 原型图 ### 1.3.1 前台 #### 1. 首页原型图 ![img](README.assets/1650888123307-38818fa3-1955-4963-b668-7a03911226fd-165224088050910.jpeg) ![img](README.assets/1651031216797-6e31716b-80d9-45c2-9d91-bf35fb731dc4-165224088446112.png) #### 2. 列表页原型图 ![img](README.assets/1650892377898-1db28ae8-6c29-4805-9e02-df8b0e078149-165224088657813.png) ![img](README.assets/1651029127891-15158b44-9e74-4016-9d61-e2676aa4cd03.png) #### 3. 详情页原型图 ![img](README.assets/1650892372578-2f5724c3-3cdc-4f6a-a375-df9b7aa5bf2c.png) #### 4. 留言页原型图 ![img](README.assets/1650892367429-99585575-6504-4f64-9d27-f78dab3ed171.png) ![img](README.assets/1651029391293-2aa31ce8-4532-4a52-8066-5df1736135b9.png) ### 1.3.2 后台 ![img](README.assets/1650892285303-5475e76e-6122-4fc4-83ca-96739e1bb239.png) ![img](README.assets/1651030671451-194e05a0-3e9f-4e07-9f86-7fce17b322ee.png) ![img](README.assets/1651030043881-0bfab572-8f20-4db6-b44c-f86500e9dc21.png) ![img](README.assets/1651030250440-df2629fa-fa83-4695-b3f4-23544237c51e.png) ![img](README.assets/1651636322122-b7fd37bd-2ae9-477e-8d95-bb74811c22d9.png) ## 1.4 需求点 ### 1.4.1 前台 #### 1. 首页 > 导航栏 - 默认进入首页页面 , `首页`显示不同颜色 - 点击`心情/旅行/美食/留言板`等分类进入相应列表页, 导航栏并显示不同颜色 - 点击`登录`, 进入登录页面 > 博文信息 - 默认加载最新发布的几篇博文 - 点击博文或`阅读全文`进入博文详细页面, 点击量增加 > 底部 - 页面右下角按钮, 点击一键回到顶部 #### 2. 列表页 > 导航栏 - 目前是哪一个分类列表, 那一个分类列表就显示不同的颜色 - 其它功能同首页 > 博文信息 - 根据时间倒序显示博文 - 点击博文或阅读全文进入博文详细页面, 点击量增加 > 底部 - 分页器, 点击页数显示不同页面数据 #### 3. 详情页 > 导航栏 - 功能同首页 > 底部 - 点击`返回上一页`即返回上一页 #### 4. 留言页面 > 导航栏 - 功能同首页 > 留言板 - 点击留言版面即可输入留言 - 点击`提交`即提交留言, 并返回首页 ### 1.4.2 后台 #### 1. 登录页面 - 输入用户名和密码后进行表单校验 - 点击`登录`即进入个人页面 - 点击退出登录即可返回登录页面 #### 2. 首页 > 左侧导航栏 > > 首页 > - e-charts饼图:分类名称和分类文章数量统计图 - e-charts柱状图:文章创建时间及文章数量统计图 #### 3. 分类管理 > 分类列表 > - 显示分类列表 - 点击添加分类按钮即可添加分类 - 点击编辑按钮即可修改分类 - 点击删除按钮即可删除分类 #### 4. 文章管理 > 文章列表 > - 显示文章列表 - 点击新增文章按钮即可新增文章 - 点击删除选中文章按钮即可删除被选定的文章 - 点击编辑按钮即可编辑文章 - 点击删除按钮即可删除文章 - 选择分类可以获取分类下的文章 > 新增文章 > - 新增文章 - 上传图片 - 文章内容也可以加入网络图片 #### 5. 留言管理 > 留言列表 > - 显示留言列表 - 点击删除留言即可删除留言 #### 6. 用户管理 > 修改用户信息 > - 修改用户信息,点击保存按钮即可修改信息 - 点击修改密码按钮,填入新密码,确认密码,点击提交即可修改密码 # 二、技术分析 ## 2.1 系统架构 ![img](README.assets/1650865550795-60f45e6d-ad1e-4764-835e-ae2218ab9d78.png) ## 2.2 技术选型 - 前台: (html/css/js)-可选jQuery, Vue.js运行在live Sever, 端口5500 - 后台:(vue+elementui), 运行端口8080 - API接口: (Express+MySQL), 运行端口3000 ## 2.3 数据库设计 > 用户表users > | 字段名 | 类型 | 字属性 | 备注 | | ----------- | ------- | --------------------- | ------------ | | id | int | 主键,自增,非空,无符号 | 用户ID | | username | char | 非空, 默认值'' | 用户名 | | password | char | 非空, 默认值'' | 用户密码 | | email | char | 默认值'' | 用户邮箱 | | user_type | char | 默认值'' | 博主类型 | | personality | varchar | 默认值'' | 用户个性签名 | > 文章表articles > | 字段名 | 类型 | 字属性 | 备注 | | ------------- | --------- | ------------------------------------------ | ---------------- | | id | int | 主键,自增,非空,无符号 | 文章ID | | title | char | 非空, 默认值'' | 文章标题 | | author | char | 非空, 默认值'' | 文章作者 | | create_time | timestamp | 默认'CURRENT_TIMESTAMP' | 文章创建时间 | | updated_time | timestamp | 默认'CURRENT_TIMESTAMP'根据当前时间戳更新 | 文章更新时间 | | abstract | varchar | 非空, 默认值'' | 文章摘要 | | content | text | 非空, 默认值'' | 文章正文 | | clicks | bigint | 默认值'0' | 文章点击量 | | category_id | int | 非空,设为外键,与categories表中的主键相连 | 文章分类ID | | iamge_address | varchar | 非空, 默认值'' | 文章封面图片路径 | > 留言板表 leave_words > | 字段名 | 类型 | 字属性 | 备注 | | ----------- | --------- | ----------------------- | ---------- | | id | int | 主键,自增,非空,无符号 | 留言ID | | name | varchar | 非空, 默认值'' | 留言者姓名 | | create_time | timestamp | 默认'CURRENT_TIMESTAMP' | 留言时间 | | content | text | 非空, 默认值'' | 留言内容 | > 分类表categories > | 字段名 | 类型 | 字属性 | 备注 | | ------ | ---- | --------------------- | -------- | | id | int | 主键,自增,非空,无符号 | 分类ID | | alias | char | 非空, 默认值'' | 分类名称 | ![image-20220506113522492](README.assets/1652056578713-708fceaf-7414-4eaa-b89b-a12dd237af44.png) ## 2.4 接口设计 ### 2.4.1 接口说明 - 接口基准地址baseURL:http://127.0.0.1:3000 - 服务端已开启cors跨域支持 - 使用code标识状态 - 数据返回格式:JSON格式 ### 2.4.2 用户管理 #### 1. 获取用户列表 - 请求路径:/users - 请求方式:GET - 成功响应 ```json { "code": 0, "message": "获取所有用户成功", "result": [ { "id": 1, "username": "周一", "password": "123456", "email": "2347563278@qq.com", "user_type": "生活类", "personality": "人生,就像一盒巧克力,你永远不知道下一块会是什么味道!《阿甘正传》" } ] } ``` #### 2. 根据id获取用户信息 - 请求路径:/users/:id - 请求方式:GET - 请求参数 | 参数名 | 参数说明 | 备注 | | :----- | :------- | -------- | | id | 用户id | 不能为空 | - 成功响应 ```json { "code": 0, "message": "获取用户成功", "result": { "id": 1, "username": "周一", "password": "123456", "email": "2347563278@qq.com", "user_type": "生活类", "personality": "人生,就像一盒巧克力,你永远不知道下一块会是什么味道!《阿甘正传》" } } ``` #### 3.添加用户 - 请求路径:/users - 请求方式:post - 成功响应 ```json { "code": 0, "message": "添加用户成功", "resutl": { "id": 2, "username": "admin-two", "password": "1234567", "email": "1234567@qq.com", "user_type": "美食", "personality": "Only food and love can not live up to." } } ``` #### 4. 修改用户 - 请求路径:/users/:id - 请求方式:put - 请求参数 | 参数名 | 参数说明 | 备注 | | :----- | :------- | -------- | | id | 用户id | 不能为空 | - 成功响应 ```json { "code": 0, "message": "修改用户成功", "result": { "id": "2", "username": "admin-three", "password": "12345678", "email": "12345678@qq.com", "user_type": "学习", "personality": "Do your best to be your best self." } } ``` #### 5. 删除用户 - 请求路径:/users/:id - 请求方式:delete - 请求参数 | 参数名 | 参数说明 | 备注 | | :----- | :------- | -------- | | id | 用户id | 不能为空 | - 成功响应 ```json { "code": 0, "message": "删除成功", "result": "" } ``` ### 2.4.3 分类管理 #### 1. 获取分类列表 - 请求路径:/categories - 请求方式:GET - 成功响应 ```json { "code": 0, "message": "获取所有分类成功", "result": [ { "id": 1, "alias": "心情" }, { "id": 2, "alias": "旅行" }, { "id": 3, "alias": "美食" } ] } ``` #### 2. 根据id获取分类列表 - 请求路径:/categories/:id - 请求方式:GET - 请求参数 | 参数名 | 参数说明 | 备注 | | :----- | :------- | -------- | | id | 用户id | 不能为空 | - 成功响应 ```json { "code": 0, "message": "根据id获取分类成功", "result": { "id": 1, "alias": "心情" } } ``` #### 3. 添加分类 - 请求路径:/categories - 请求方式:POST - 成功响应 ```json { "code": 0, "message": "添加分类成功", "result": { "id": 6, "alias": "生活" } } ``` #### 4. 修改分类 - 请求路径:/categories/:id - 请求方式:PUT - 请求参数 | 参数名 | 参数说明 | 备注 | | :----- | :------- | -------- | | id | 用户id | 不能为空 | - 成功响应 ```json { "code": 0, "message": "修改分类成功", "result": { "id": "6", "alias": "梦想" } } ``` #### 5. 删除分类 - 请求路径:/categories/:id - 请求方式:delete - 请求参数 | 参数名 | 参数说明 | 备注 | | :----- | :------- | -------- | | id | 用户id | 不能为空 | - 成功响应 ```json { "code": 0, "message": "删除成功", "result": "" } ``` ### 2.4.4 文章管理 #### 1. 获取文章列表 - 请求路径:/articles - 请求方式:GET - 请求参数 | 参数名 | 参数说明 | 备注 | | ----------- | ------------ | -------- | | category_id | 分类ID | 不能为空 | | page | 当前页数 | 不能为空 | | size | 每页显示条数 | 不能为空 | - 响应参数 | 参数名 | 参数说明 | | ------ | ---------------- | | total | 文章总数 | | totalC | 各分类文章数量 | | dataAA | 全部文章 | | dataA | 分页文章 | | dataCC | 分类后的文章 | | dataC | 分页,分类文章 | | clicks | 点击量前五的文章 | | datad | echars分类及数量 | | datae | echars时间及数量 | - 成功响应 ```json { "code": 0, "message": "获取文章成功", "result": { "total": 9, "totalC": [略], "dataAA": [略], "dataA": [略], "dataCC": [略], "dataC": [略], "clicks": [略], "datad": [略], "datae": [略] } } ``` #### 2. 根据id获取文章 - 请求路径:/articles/:id - 请求方式:GET - 请求参数 | 参数名 | 参数说明 | 备注 | | :----- | :------- | -------- | | id | 用户id | 不能为空 | - 成功响应 ```json { "code": 0, "message": "根据id获取文章成功", "result": { "id": 1, "abstract": "夜晚,当你抬头仰望星空,发现星空的景⾊是那样迷⼈,⼜令你留连不舍,那么你便拥有了⼀份难得的财富。", "author": "周一", "clicks": 0, "content": "略", "create_time": "2022-04-15 15:41:57", "title": "关注生活的点滴也可以很幸福", "updated_time": "2022-04-30 09:07:24", "image_address": "http://localhost:3000/upload/1.webp.jpg", "alias": "心情" } } ``` #### 3. 添加文章 - 请求路径:/articles - 请求方式:post - 成功响应 ```json { "code": 0, "message": "添加文章成功", "resutl": { "resData": { "id": 2, "title": "旅游", "author": "pro", "create_time": "2022-05-04 13:25:04", "updated_time": "2022-05-04 13:25:04", "abstract": "2", "content": "1234", "clicks": 0, "category_id": 2, "image_address": "E:/胡宇/GIS软件开发/代码/胡宇写的项目/个人博客项目/404.jpg", "alias": "旅行" } } } ``` #### 4. 修改文章 - 请求路径:/articles/:id - 请求方式:put - 请求参数 | 参数名 | 参数说明 | 备注 | | :----- | :------- | -------- | | id | 用户id | 不能为空 | - 成功响应 ```json { "code": 0, "message": "修改用户成功", "result": { "resData": { "id": 1, "title": "生气", "author": "angry", "create_time": "2022-05-04 13:25:04", "updated_time": "2022-05-04 13:27:25", "abstract": "2", "content": "abc", "clicks": 0, "category_id": 1, "image_address": "E:/胡宇/GIS软件开发/代码/胡宇写的项目/个人博客项目/404.jpg", "alias": "心情" } } } ``` #### 5. 删除文章 - 请求路径:/articles/:id - 请求方式:delete - 请求参数 | 参数名 | 参数说明 | 备注 | | :----- | :------- | -------- | | id | 用户id | 不能为空 | - 成功响应 ```json { "code": 0, "message": "删除成功", "result": "" } ``` ### 2.4.5 留言管理 #### 1. 获取留言列表 - 请求路径:/leavewords - 请求方式:GET - 成功响应 ```json { "code": 0, "message": "获取留言成功", "result": { "total": 4, "data": [ { "id": 1, "created_time": "2022-04-26 10:17:55", "content": "内容很有趣,支持小编!" }, { "id": 2, "created_time": "2022-04-27 20:23:27", "content": "求更新" } ] } } ``` #### 2. 添加留言 - 请求路径:/leavewords - 请求方式:post - 成功响应 ```json { "code": 0, "message": "添加留言成功", "resutl": { "id": 5, "content": "太棒了" } } ``` #### 3.删除留言 - 请求路径:/leavewords/:id - 请求方式:delete - 请求参数 | 参数名 | 参数说明 | 备注 | | :----- | :------- | -------- | | id | 用户id | 不能为空 | - 成功响应 ```json { "code": 0, "message": "删除成功", "result": "" } ``` # 三、WBS ## 3.1 项目计划表 计划3个人一人负责一个模块(前端、中后端、后端), 先完成的成员再帮助其他成员 项目计划表见:https://xzd-gis.yuque.com/staff-zxaegl/tfen68/zg9gpg#UxCb ## 3.2 项目实施表 在实施过程中将三个模块的基本雏形搭建出来后为了锻炼能力, 使成员对三个模块都有一定的掌握, 就根据实际情况修改了项目计划, 让各个成员都参加到各个模块的逻辑编写中 组长在每天统计填写 具体进度见:https://xzd-gis.yuque.com/staff-zxaegl/tfen68/nyzkgd#UxCb # 四、具体开发 # 五、整合联调 # 六、项目答辩汇报 # 七、项目总结 ## 7.1 印象深刻的调试过程 ### 1. 前台 > 问题一: 前台怎么搭建没有理清,特别是页面之间如何跳转并且重新渲染数据,错把数据的传递认为是'事件总线' 这是不应该的,我也深刻发现了,我知识的刻板 > 解决: 要搞清楚前台是在HTML中使用vue,还是vue中使用HTML,这是两种不同的思路 也可以通过路径携带参数(数据),再解析路径获取参数(数据) ![image-20220508211005886](README.assets/1652056362684-7197967f-d763-455d-9e86-990fe1ba2375.png) ![image-20220508211051548](README.assets/1652056366159-f8945db0-1bc6-45e1-bd54-1372a67abc57.png) ### 2. 中后台 > 问题一: 如何处理管理员登录,token的运用 > 解决: 对于新的知识点要注意理清思路,画一下流程图 在网上看到的demo,可能并不能做到与我们的项目情况完全一致,所以我们可以自己写一个demo,理清思路 ![管理员登录—JWT](README.assets/1652056398247-98a71fe4-07b5-40c3-8171-a4f0a3c829d4.png) > 问题二: 文章列表中,一开始以为是'删除文章后,分类列表无显示',实际上是'全部文章列表'分页后,再选择分类文章列表无显示。 ![image-20220509074948042](README.assets/1652056415963-f3bfa810-b5d3-4d8b-a6da-f9fa28f25db8.png) > 解决: 1. 首先,要理清问题的源头,知道是什么引起的,在这部分耽误了很多时间去处理 2. 由于一开始以为的是'删除文章后再选择分类,不好使',所以要清楚'删除文章的功能'是否有问题,如果没有问题那就是'选择分类有问题' 3. 再判断选择分类哪里有问题,由于没有报错和飘红,因此判断请求和语法都没有问题,所以是逻辑的问题 4. 检查逻辑,最终确定是**由于页码page变化后(page不是第一页),再选择分类,由于分类的文章列表页数只有一页,并且当时page不为1,所以即便获取数据成功也显示无数据** 5. 选择分类后,为page重新赋初值,即可解决这个问题 > 总结: 遇到问题时,理清思路,找到问题的核心是关键 ![image-20220509080230671](README.assets/1652056421646-5f2b8a0d-037c-48b7-852b-f43da9bd2ef9.png) ### 3. 后台 > 问题一: 在只想通过一个路由接口`/article`的前提下,如何获取多种数据 > 解决一:写不同的接口 1. 优点:清晰,不占内存 2. 缺点:文件夯长,可复用性不好 3. 例如: - 获取所有文章+分页 ```http GET {{baseUrl}} /article?page=1&size=3 ``` - 分类查询文章+分页 ```http GET {{baseUrl}} /article/category?categoty_id=1&page=1&size=3 ``` > 解决二:写一个接口,通过不同的sql语句,同时获取不同的数据,发送请求时需要哪个调用哪个 1. 优点:可复用性好 2. 缺点:无论要获取什么数据都要传三个参数,每次请求会获取所有数据,占内存(下次不能这么写) 3. 例如: ```http GET {{baseUrl}} /article?categoty_id=1&page=1&size=3 ``` ```js //成功的响应 { "code": 0, "message": "获取文章成功", "result": { "total": 9,//文章总数 "totalC": [略],//分类后的文章数量 "dataAA": [略],//获取文章全部 "dataA": [略], // 分页+文章 "dataCC": [略], //分类 "dataC": [略],//分类+分页 "clicks": [略],//点击量前五 "datad": [略],//echars分类及数量 "datae": [略]//echars时间及数量 } } ``` ## 7.2 项目心得体会 ### 1. 项目实施前 ​ 完善的需求分析十分必要(特别是接口的设计),既是提前准备的过程,也是理清思路的过程,从而更好的把握项目的易、难点,有利于对整个项目的进度以及分工的安排,事半功倍 ​ 自己首先要清楚本次项目的目的是什么,是为了结果还是过程 ### 2. 实施过程中 1. 遇到问题很正常,但要始终把握问题的源头,不要痴迷于某一细节,从而越走越偏 2. 遇到较难的功能,可以适当放放,先完成有思路的功能,以免耽误进度 3. 当在调试时出现bug,但又没有飘红或报错时,多半是逻辑的问题,首先要找到可能出现的位置,通过'打断点','在控制台打印','查看network'等相结合,从而找清错误的位置 4. 在书写代码的过程中,思维还是比较死板,很容易出现'没想到'的情况,或者时是解决的方法比较笨,这还是因为对知识点掌握的不够灵活 5. 因此在平时的学习过程中,不能只看知识的表面,更重要的是知识点之间的相互联系 6. 当发现对之前的知识遗忘了的时候,千万不能懒,不要怕耽误项目的进度,一定要及时翻笔记,及时巩固!!! ### 3. 合作 ​ 项目的完成是否成功,组员之间的合作十分重要,当遇到问题时及时沟通,相互帮助 ​ 有时在自己遇到问题时,自己很难解决,但是别人一看可能很快就解决,这就是'旁观者清'吧 **总而言之:多练习,多复习,串联知识点,否则很容易忘!!!**