├── .gitignore
├── MongodbData
├── routes.json
├── timeclues.json
└── users.json
├── MyBlogAdmin
├── .browserslistrc
├── .eslintrc.js
├── babel.config.js
├── jsconfig.json
├── package.json
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── App.vue
│ ├── api
│ │ ├── api.js
│ │ └── request.js
│ ├── assets
│ │ ├── bg.jpg
│ │ ├── conmon.css
│ │ └── prefixfree.js
│ ├── components
│ │ ├── Foot.vue
│ │ ├── Head.vue
│ │ └── Nav.vue
│ ├── main.js
│ ├── router
│ │ ├── index.js
│ │ └── router.js
│ ├── store
│ │ ├── blogs.js
│ │ ├── classify.js
│ │ ├── index.js
│ │ ├── jotting.js
│ │ ├── route.js
│ │ ├── tags.js
│ │ └── user.js
│ ├── util
│ │ ├── directive.js
│ │ └── index.js
│ └── views
│ │ ├── 404.vue
│ │ ├── Admin.vue
│ │ ├── Article.vue
│ │ ├── DataBoard.vue
│ │ ├── Log.vue
│ │ ├── LoginOrRegister.vue
│ │ ├── Markdown.vue
│ │ ├── Photo.vue
│ │ ├── Result.vue
│ │ ├── Route.vue
│ │ ├── Self.vue
│ │ ├── Timeclue.vue
│ │ └── User.vue
├── vue.config.js
└── yarn.lock
├── MyBlogFront
├── .browserslistrc
├── .eslintrc.js
├── babel.config.js
├── jsconfig.json
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.css
│ └── index.html
├── src
│ ├── App.vue
│ ├── api
│ │ ├── api.js
│ │ ├── index.js
│ │ └── request.js
│ ├── assets
│ │ ├── common.css
│ │ ├── icons
│ │ │ ├── iconfont.css
│ │ │ ├── iconfont.ttf
│ │ │ ├── iconfont.woff
│ │ │ └── iconfont.woff2
│ │ ├── img
│ │ │ ├── avatar.png
│ │ │ ├── infoBg.jpg
│ │ │ ├── lightBg.png
│ │ │ ├── nightBg.jpg
│ │ │ └── slideBg
│ │ │ │ ├── slidebg1.jpg
│ │ │ │ ├── slidebg2.jpg
│ │ │ │ └── slidebg3.jpg
│ │ └── logo.png
│ ├── components
│ │ ├── Comment.vue
│ │ ├── Footer.vue
│ │ ├── Header.vue
│ │ ├── Loading
│ │ │ ├── Loading.vue
│ │ │ └── index.js
│ │ ├── Nav.vue
│ │ ├── SiderInfo.vue
│ │ ├── Slideshow.vue
│ │ └── Switch.vue
│ ├── main.js
│ ├── router
│ │ └── index.js
│ ├── store
│ │ ├── index.js
│ │ ├── synthesis.js
│ │ └── theme.js
│ ├── util
│ │ ├── bgSpecialEffect.js
│ │ ├── clickSpecialEffect.js
│ │ └── index.js
│ └── views
│ │ ├── About.vue
│ │ ├── Article.vue
│ │ ├── List.vue
│ │ ├── MessageBoard.vue
│ │ ├── PhotoWall.vue
│ │ └── TimeClue.vue
├── vue.config.js
└── yarn.lock
├── MyBlogServe
├── app.js
├── bin
│ └── www
├── controllers
│ ├── blogs.js
│ ├── classifies.js
│ ├── comments.js
│ ├── jottings.js
│ ├── murmur.js
│ ├── photo.js
│ ├── routes.js
│ ├── synthesis.js
│ ├── timeclue.js
│ └── users.js
├── db
│ └── connect.js
├── keys
│ ├── rsa_private_key.pem
│ └── rsa_public_key.pem
├── model
│ ├── blogs.js
│ ├── classifies.js
│ ├── comments.js
│ ├── jottings.js
│ ├── murmurs.js
│ ├── photo.js
│ ├── routes.js
│ ├── tag.js
│ ├── timeclue.js
│ └── users.js
├── package.json
├── public
│ ├── avatars
│ │ ├── 1661779453078
│ │ └── 1662256970035
│ ├── photos
│ │ ├── 1662046452834
│ │ ├── 1662046521921
│ │ ├── 1662046564119
│ │ ├── 1662046595682
│ │ ├── 1662047030636
│ │ ├── 1662047054759
│ │ ├── 1662047189170
│ │ ├── 1662049020699
│ │ ├── 1662049188808
│ │ ├── 1662049270170
│ │ ├── 1662049353519
│ │ ├── 1662049446197
│ │ ├── 1662049505602
│ │ ├── 1662049548427
│ │ ├── 1662049654510
│ │ ├── 1662049758833
│ │ ├── 1662049791176
│ │ ├── 1662049883085
│ │ ├── 1662050480857
│ │ └── 1662050583435
│ └── stylesheets
│ │ └── style.css
├── routes
│ ├── blogs.js
│ ├── classifies.js
│ ├── comments.js
│ ├── jottings.js
│ ├── murmur.js
│ ├── photo.js
│ ├── routes.js
│ ├── synthesis.js
│ ├── timeclue.js
│ └── users.js
├── utils
│ └── index.js
├── views
│ ├── error.jade
│ ├── index.jade
│ └── layout.jade
└── yarn.lock
├── README.md
├── ReadmeImg
├── 1.png
├── 10.png
├── 11.png
├── 12.png
├── 13.png
├── 14.png
├── 15.png
├── 2.png
├── 3.png
├── 4.png
├── 5.png
├── 6.png
├── 7.png
├── 8.png
└── 9.png
└── default.conf
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | /dist
4 | .gitignore
5 |
6 |
7 | # local env files
8 | .env.local
9 | .env.*.local
10 |
11 | # Log files
12 | npm-debug.log*
13 | yarn-debug.log*
14 | yarn-error.log*
15 | pnpm-debug.log*
16 |
17 | # Editor directories and files
18 | .idea
19 | .vscode
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 | node_modules
26 |
--------------------------------------------------------------------------------
/MongodbData/routes.json:
--------------------------------------------------------------------------------
1 | [{
2 | "_id": {
3 | "$oid": "6314288d53aa7200deac6936"
4 | },
5 | "path": "article",
6 | "name": "文章管理",
7 | "component": "Article.vue",
8 | "limits": [
9 | "管理员",
10 | "普通用户"
11 | ],
12 | "meta": {
13 | "icon": "el-icon-document"
14 | }
15 | },{
16 | "_id": {
17 | "$oid": "6314288d53aa7200deac6939"
18 | },
19 | "path": "photo",
20 | "name": "照片管理",
21 | "component": "Photo.vue",
22 | "limits": [
23 | "管理员",
24 | "普通用户"
25 | ],
26 | "meta": {
27 | "icon": "el-icon-menu"
28 | }
29 | },{
30 | "_id": {
31 | "$oid": "6314288d53aa7200deac693c"
32 | },
33 | "path": "markdown",
34 | "name": "编辑文章",
35 | "component": "Markdown.vue",
36 | "limits": [
37 | "管理员",
38 | "普通用户"
39 | ],
40 | "meta": {
41 | "icon": "el-icon-edit"
42 | }
43 | },{
44 | "_id": {
45 | "$oid": "6314288d53aa7200deac693f"
46 | },
47 | "path": "timeclue",
48 | "name": "时间节点管理",
49 | "component": "Timeclue.vue",
50 | "limits": [
51 | "管理员",
52 | "普通用户"
53 | ],
54 | "meta": {
55 | "icon": "el-icon-notebook-1"
56 | }
57 | },{
58 | "_id": {
59 | "$oid": "6314288d53aa7200deac6942"
60 | },
61 | "path": "routingmanage",
62 | "name": "路由管理",
63 | "component": "Route.vue",
64 | "limits": [
65 | "管理员"
66 | ],
67 | "meta": {
68 | "icon": "el-icon-rank"
69 | }
70 | },{
71 | "_id": {
72 | "$oid": "6314288d53aa7200deac6945"
73 | },
74 | "path": "user",
75 | "name": "用户管理",
76 | "component": "User.vue",
77 | "limits": [
78 | "管理员"
79 | ],
80 | "meta": {
81 | "icon": "el-icon-s-custom"
82 | }
83 | },{
84 | "_id": {
85 | "$oid": "6314288d53aa7200deac6948"
86 | },
87 | "path": "logs",
88 | "name": "日志",
89 | "component": "Log.vue",
90 | "limits": [
91 | "管理员"
92 | ],
93 | "meta": {
94 | "icon": "el-icon-setting"
95 | }
96 | },{
97 | "_id": {
98 | "$oid": "6315efa453aa7200deac7a78"
99 | },
100 | "path": "result",
101 | "name": "结果页",
102 | "component": "Result.vue",
103 | "limits": [
104 | "管理员",
105 | "普通用户"
106 | ],
107 | "meta": {
108 | "NotShow": true
109 | }
110 | },{
111 | "_id": {
112 | "$oid": "6315f83453aa7200deac7d30"
113 | },
114 | "path": "self",
115 | "name": "个人中心",
116 | "component": "Self.vue",
117 | "limits": [
118 | "管理员",
119 | "普通用户"
120 | ],
121 | "meta": {
122 | "icon": "el-icon-s-check"
123 | }
124 | }]
--------------------------------------------------------------------------------
/MongodbData/timeclues.json:
--------------------------------------------------------------------------------
1 | [{
2 | "_id": {
3 | "$oid": "630f625353aa7200deabcd45"
4 | },
5 | "title": "持续开发中, 敬请期待...",
6 | "state": false,
7 | "date": "2022-09-07",
8 | "digest": "持续开发中, 敬请期待..."
9 | },{
10 | "_id": {
11 | "$oid": "630f626453aa7200deabcd4f"
12 | },
13 | "date": "2022-07-31",
14 | "state": true,
15 | "title": "前后端联调,完善系统,开发新功能",
16 | "digest": "规范了前后端代码,完善了部分代码,新增了功能:注册、后台管理系统:权限管理、路由管理、图片上传;前端展示部分:评论、留言板、关于、小站时间线、优化了切换效果,。"
17 | },{
18 | "_id": {
19 | "$oid": "630f626f53aa7200deabcd56"
20 | },
21 | "date": "2022-07-25",
22 | "state": true,
23 | "title": "前端部分基础功能完成",
24 | "digest": "完成了前端的基础功能,管理系统:登录、用户管理、博客管理、随笔管理、使用markdown语法新增博客随笔;展示部分:博客展示、随笔展示。"
25 | },{
26 | "_id": {
27 | "$oid": "630f627a53aa7200deabcd5d"
28 | },
29 | "date": "2022-07-14",
30 | "state": true,
31 | "title": "后端基础功能完成",
32 | "digest": "完成了后端基础工功能的接口设计与实现"
33 | },{
34 | "_id": {
35 | "$oid": "630f628453aa7200deabcd64"
36 | },
37 | "date": "2022-06-25",
38 | "state": true,
39 | "title": "项目搭建完成",
40 | "digest": "完成项目环境的搭建、静态页面的编写和一些必要组件、方法的封装"
41 | },{
42 | "_id": {
43 | "$oid": "630f628d53aa7200deabcd69"
44 | },
45 | "date": "2022-06-25",
46 | "state": true,
47 | "title": "前期准备工作",
48 | "digest": "在网上查找个人博客相关资料,查看优秀的个人博客作品,分析自己的需求,确定使用什么技术,完成数据库的设计。"
49 | },{
50 | "_id": {
51 | "$oid": "630f629653aa7200deabcd6e"
52 | },
53 | "date": "2022-06-20",
54 | "state": true,
55 | "title": "确定博客项目",
56 | "digest": "大发大"
57 | },{
58 | "_id": {
59 | "$oid": "63189d281ac7353c8b30acad"
60 | },
61 | "date": "2022-08-20T00:00:00.000Z",
62 | "title": "小站第一次上线",
63 | "digest": "所有功能基本完善,尝试第一次上线。",
64 | "__v": 0,
65 | "state": true
66 | }]
--------------------------------------------------------------------------------
/MongodbData/users.json:
--------------------------------------------------------------------------------
1 | [{
2 | "_id": {
3 | "$oid": "6313fb41c2377786e8339d70"
4 | },
5 | "username": "管理员",
6 | "password": "$2b$10$LcM347ZIT4upIpm70zBHEOFXM6pXe2fXgfmPXUGzdLiThjkTbNyCW",
7 | "email": "123@qq.com",
8 | "date": {
9 | "$date": {
10 | "$numberLong": "1662253889206"
11 | }
12 | },
13 | "role": "管理员",
14 | "__v": 0
15 | },{
16 | "_id": {
17 | "$oid": "6319fd5eccef1193b5e48760"
18 | },
19 | "username": "普通用户",
20 | "password": "$2b$10$G0H7p87B.vTw90ppA.c9q.AlcRDPEVBUK731gnUO1mknQVC0DmlQC",
21 | "email": "234@qq.com",
22 | "date": {
23 | "$date": {
24 | "$numberLong": "1662647646590"
25 | }
26 | },
27 | "role": "普通用户",
28 | "__v": 0
29 | }]
--------------------------------------------------------------------------------
/MyBlogAdmin/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/MyBlogAdmin/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | 'extends': [
7 | 'plugin:vue/essential',
8 | 'eslint:recommended'
9 | ],
10 | parserOptions: {
11 | parser: '@babel/eslint-parser'
12 | },
13 | rules: {
14 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
15 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/MyBlogAdmin/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset'
4 | ],
5 | plugins: [
6 | [
7 | "component",
8 | {
9 | "libraryName": "element-ui",
10 | "styleLibraryName": "theme-chalk"
11 | }
12 | ]
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/MyBlogAdmin/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "esnext",
5 | "baseUrl": "./",
6 | "moduleResolution": "node",
7 | "paths": {
8 | "@/*": [
9 | "src/*"
10 | ]
11 | },
12 | "lib": [
13 | "esnext",
14 | "dom",
15 | "dom.iterable",
16 | "scripthost"
17 | ]
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/MyBlogAdmin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "myblogadmin",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "axios": "^0.26.1",
12 | "core-js": "^3.8.3",
13 | "echarts": "^5.3.3",
14 | "element-ui": "^2.15.6",
15 | "mavon-editor": "^2.10.4",
16 | "nprogress": "^0.2.0",
17 | "vue": "^2.6.14",
18 | "vue-router": "^3.5.1",
19 | "vuex": "^3.6.2"
20 | },
21 | "devDependencies": {
22 | "@babel/core": "^7.12.16",
23 | "@babel/eslint-parser": "^7.12.16",
24 | "@vue/cli-plugin-babel": "~5.0.0",
25 | "@vue/cli-plugin-eslint": "~5.0.0",
26 | "@vue/cli-plugin-router": "~5.0.0",
27 | "@vue/cli-plugin-vuex": "~5.0.0",
28 | "@vue/cli-service": "~5.0.0",
29 | "babel-plugin-component": "^1.1.1",
30 | "compression-webpack-plugin": "^10.0.0",
31 | "eslint": "^7.32.0",
32 | "eslint-plugin-vue": "^8.0.3",
33 | "less": "^4.0.0",
34 | "less-loader": "^8.0.0",
35 | "vue-template-compiler": "^2.6.14"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/MyBlogAdmin/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogAdmin/public/favicon.ico
--------------------------------------------------------------------------------
/MyBlogAdmin/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | 孤城浪人的博客(后台管理)
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/api/api.js:
--------------------------------------------------------------------------------
1 | // 统一管理所有接口
2 | import requests from "./request";
3 | // 获取文章列表
4 | export const getBlogs = () => requests.get("/blogs/getblogs");
5 | // 更新文章
6 | export const updateBlog = data => requests.post("/blogs/updateblog", data);
7 | // 删除文章
8 | export const deleteBlog = (params = {}) => requests.delete("/blogs/deleteblog", { params });
9 | // 修改文章状态
10 | export const changeBlogState = params => requests.get("/blogs/changeblogstate", { params });
11 | // 增加文章
12 | export const addBlog = data => requests.post("/blogs/addblog", data);
13 | // 获取某一文章
14 | export const getBlog = params => requests.get("/blogs/getblog", { params });
15 |
16 | // 登录
17 | export const login = data => requests.post("/users/login", data);
18 | // 获取用户信息
19 | export const getUsers = () => requests.get("/users/getusers");
20 | // 删除用户
21 | export const deleteUser = params => requests.delete("/users/deleteuser", { params });
22 | // 注册用户
23 | export const register = data => requests.post("/users/register", data);
24 | // 修改用户信息
25 | export const updateUserInfo = data => requests.post("/users/updateuserinfo", data);
26 | // 修改密码
27 | export const updatePassword = data => requests.post("/users/updatepassword", data);
28 | // 退出
29 | export const logout = () => requests.get("/users/logout");
30 | // 获取某个用户信息
31 | export const getUser = params => requests.get("/users/getuser", { params });
32 |
33 | // 获取专栏列表
34 | export const getClassifies = () => requests.get("/classifies/getclassifies");
35 | // 删除专栏
36 | export const deleteClassify = params => requests.delete("/classifies/deleteclassify", { params });
37 | // 编辑专栏
38 | export const updateClassifyTitle = data => requests.post("/classifies/updateclassifytitle", data);
39 | // 新增专栏
40 | export const addClassify = data => requests.post("/classifies/addclassify", data);
41 |
42 | // 获取随笔列表
43 | export const getJottings = () => requests.get("/jottings/getjottings");
44 | // 修改状态
45 | export const changeJottingState = params => requests.get("/jottings/changestate", { params });
46 | // 删除随笔
47 | export const deleteJotting = params => requests.delete("/jottings/deletejotting", { params });
48 | // 添加随笔
49 | export const addJotting = data => requests.post("/jottings/addjotting", data);
50 | // 获取某一随笔
51 | export const getJotting = params => requests.get("/jottings/getjotting", { params });
52 | // 添加图片
53 | export const uploadImg = data => requests.post("/synthesis/uploadartimg", data, { headers: { "content-type": "multipart/form-data" } });
54 | // 添加随笔
55 | export const updateJotting = data => requests.post("/jottings/updatejotting", data);
56 |
57 | // 添加一级路由
58 | export const addFirstRoute = data => requests.post("/routes/addfirstroute", data);
59 | // 添加二级路由
60 | export const addSecondRoute = data => requests.post("/routes/addsecondroute", data);
61 | // 修改路由
62 | export const updateRoute = data => requests.post("/routes/updatroute", data);
63 | // 删除路由
64 | export const deleteRoute = params => requests.delete("/routes/deleteroute", { params });
65 | // 获取路由
66 | export const getRoutes = params => requests.get("/routes/getroutes", { params });
67 | // 获取所有路由
68 | export const getRouteList = () => requests.get("/routes/getroutelist");
69 |
70 | // 添加书签
71 | export const addTag = data => requests.post("/synthesis/addtag", data);
72 | // 获取书签
73 | export const getTags = () => requests.get("/synthesis/gettags");
74 | // 修改书签
75 | export const updateTag = data => requests.post("/synthesis/updatetag", data);
76 | // 删除书签
77 | export const deleteTag = params => requests.delete("/synthesis/deletetag", { params });
78 |
79 | // 修改游客信息
80 | export const getMurmurInfos = () => requests.get("/murmur/getmurmurinfos");
81 | // 删除游客信息
82 | export const deleteMurmurInfo = params => requests.delete("/murmur/deletemurmurinfo", { params });
83 |
84 | // 获取所有照片信息
85 | export const getPhotos = () => requests.get("/photo/getphotos");
86 | // 修改照片信息
87 | export const updatePhotos = data => requests.post("/photo/updatephotodigest", data);
88 | // 删除照片信息
89 | export const deletePhoto = params => requests.delete("/photo/deletephoto", { params });
90 | // 新增照片信息
91 | export const addPhoto = data => requests.post("/photo/addphoto", data);
92 |
93 | // 获取所有评论
94 | export const getComments = () => requests.get("/comments/getcomments");
95 | // 删除一级评论
96 | export const deleteFirstComment = params => requests.delete("/comments/deletefirstcomment", { params });
97 | // 删除二级评论
98 | export const deleteSecondComment = params => requests.delete("/comments/deletesecondcomment", { params });
99 |
100 | // 获取所有时间节点
101 | export const getTimeclues = () => requests.get("/timeclues/gettimeclues");
102 | // 删除时间节点
103 | export const deleteTimeclue = params => requests.delete("/timeclues/deletetimeclue", { params });
104 | // 修改时间节点
105 | export const updateTimeclue = data => requests.post("/timeclues/updatetimeclue", data);
106 | // 新增时间节点
107 | export const addTimeclue = data => requests.post("/timeclues/addtimeclue", data);
108 | // 改变时间节点状态
109 | export const changeTimeNodeState = params => requests.get("/timeclues/changetimenodestate", { params });
110 | // 改变时间节点状态
111 | export const getDataForDataBoard = () => requests.get("/synthesis/getdatafordataboard");
112 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/api/request.js:
--------------------------------------------------------------------------------
1 | // 引入axios进行二次封装
2 | // import axios from "axios";
3 | // 进度条
4 | import nprogress from "nprogress";
5 | // 引入进度条样式
6 | import "nprogress/nprogress.css";
7 | import store from "@/store";
8 | const requests = axios.create({
9 | // 配置对象
10 | // 基础路径
11 | baseURL: "/api",
12 | // 请求超时的时间限 制
13 | timeout: 5000,
14 | });
15 | // 请求拦截器:在请求发出去之前做处理
16 | requests.interceptors.request.use(
17 | config => {
18 | // config:配置对象,对象信息里边有一个重要信息,请求头headers
19 | nprogress.start();
20 | // // 需要携带token带给服务器
21 | if (store.state.user.token || localStorage.getItem("TOKEN")) {
22 | config.headers.token = store.state.user.token;
23 | }
24 | return config;
25 | },
26 | error => {
27 | //请求错误时
28 | console.log("request:", error);
29 | // 1.判断请求超时
30 | if (error.code === "ECONNABORTED" && error.message.indexOf("timeout") !== -1) {
31 | console.log("timeout请求超时");
32 | return service.request(originalRequest); // 再重复请求一次
33 | }
34 | return Promise.reject(error);
35 | }
36 | );
37 | // 响应拦截器
38 | requests.interceptors.response.use(
39 | res => {
40 | // 进度条结束
41 | nprogress.done();
42 | return res.data;
43 | },
44 | err => {
45 | nprogress.done();
46 | //console.log('response:',err)
47 | // 1.判断请求超时
48 | if (err.code === "ECONNABORTED" && err.message.indexOf("timeout") !== -1) {
49 | return Promise.reject("timeout请求超时");
50 | // return service.request(originalRequest);// 再重复请求一次
51 | }
52 | if (err.message.indexOf("Network") !== -1) {
53 | return Promise.reject("网络异常");
54 | }
55 | if (err.response && err.response.status === 404) {
56 | return Promise.reject("请求的资源无法找到");
57 | } else if (err.response && err.response.status === 500) {
58 | return Promise.reject("服务器繁忙");
59 | }
60 | console.log(err.response.status);
61 | return Promise.reject(err);
62 | }
63 | );
64 |
65 | export default requests;
66 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/assets/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogAdmin/src/assets/bg.jpg
--------------------------------------------------------------------------------
/MyBlogAdmin/src/assets/conmon.css:
--------------------------------------------------------------------------------
1 | /* el-table和el-dialog样式 */
2 | .el-table__cell,
3 | .el-dialog,
4 | .el-table tr {
5 | background-color: #323232 !important;
6 | }
7 | .el-table {
8 | background-color: transparent;
9 | color: #ddd;
10 | }
11 | .el-tabs__content {
12 | height: calc(100% - 55px);
13 | }
14 |
15 | .is-active {
16 | color: #409eff;
17 | box-shadow: none !important;
18 | }
19 | .el-dialog{
20 | position: absolute;
21 | left: 50%;
22 | top: 50%;
23 | transform: translate(-50%, -50%);
24 | margin-top: 0 !important;
25 | }
26 |
27 | .el-dialog__title,
28 | .el-form-item__label,
29 | .el-tabs__item {
30 | color: #ddd;
31 | }
32 |
33 | /* markdown插件样式 */
34 | .v-note-edit,
35 | .content-input-wrapper,
36 | .v-note-op,
37 | .v-note-panel,
38 | .op-icon.selected,
39 | .v-note-read-model,
40 | .auto-textarea-input,
41 | .v-show-content {
42 | background-color: #323232 !important;
43 | }
44 | .auto-textarea-input,
45 | .v-show-content {
46 | color: #ccc !important;
47 | }
48 | .op-icon.selected,
49 | .v-note-read-model {
50 | color: #757575 !important;
51 | }
52 | /* 抽屉样式 */
53 | .el-drawer {
54 | background-color: #323232;
55 | }
56 | .drawer-footer {
57 | display: flex;
58 | justify-content: center;
59 | }
60 | .el-input {
61 | width: 80% !important;
62 | }
63 | .el-select {
64 | width: 100%;
65 | }
66 |
67 |
68 |
69 | a {
70 | text-decoration: none;
71 | }
72 | * {
73 | margin: 0;
74 | padding: 0;
75 | }
76 | ::-webkit-scrollbar {
77 | /*滚动条整体样式*/
78 | width: 5px;
79 | }
80 |
81 | ::-webkit-scrollbar-thumb {
82 | /*滚动条里面小方块*/
83 | border-radius: 5px;
84 | background: rgb(100, 100, 100);
85 | }
86 |
87 | ::-webkit-scrollbar-track {
88 | /*滚动条里面轨道*/
89 | border-radius: 0;
90 | opacity: 0;
91 | /* background: rgba(0, 0, 0, 0); */
92 | }
93 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/components/Foot.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
11 |
13 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/components/Head.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
MyBlog后台管理
4 |
5 |
6 |
8 |
9 |
10 | 退出登录
11 |
12 |
13 | {{ username }}
14 |
15 |
16 |
17 |
64 |
91 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/components/Nav.vue:
--------------------------------------------------------------------------------
1 |
2 |
48 |
49 |
58 |
66 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/main.js:
--------------------------------------------------------------------------------
1 | // import Vue from "vue";
2 | import App from "@/App.vue";
3 | import router from "@/router";
4 | import store from "@/store";
5 | // import "element-ui/lib/theme-chalk/index.css";
6 | // import element from "element-ui";
7 | import { has } from "./util/directive";
8 | import "@/assets/conmon.css";
9 |
10 | // Vue.use(element);
11 | new Vue({
12 | router,
13 | store,
14 | render: h => h(App),
15 | }).$mount("#app");
16 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/router/index.js:
--------------------------------------------------------------------------------
1 | // import Vue from "vue";
2 | import VueRouter from "vue-router";
3 | import { routes } from "./router";
4 | import { getToken, getUserInfo } from "@/util";
5 | import store from "@/store";
6 | Vue.use(VueRouter);
7 |
8 | const router = new VueRouter({
9 | mode: "history",
10 | base: process.env.BASE_URL,
11 | routes,
12 | });
13 | let flag = true;
14 | router.beforeEach(async (to, from, next) => {
15 | // 如果已登录
16 | if (getToken()) {
17 | try {
18 | if (to.path === "/loginorregister") {
19 | next("/admin");
20 | } else {
21 | if (flag) {
22 | // 判断当前用户是否已拉取完user_info信息
23 | await store.dispatch("getRoutes", getUserInfo().role);
24 | store.getters.routes.forEach(item => {
25 | router.addRoute("home", {
26 | path: item.path,
27 | name: item.name,
28 | component: () => import(`@/views/${item.component}`),
29 | meta: item.meta,
30 | });
31 | });
32 | flag = false;
33 | next({ ...to, replace: true });
34 | console.log(router.getRoutes());
35 | } else {
36 | next();
37 | }
38 | }
39 | } catch (err) {
40 | console.log(err);
41 | }
42 | } else {
43 | //未登录
44 | if (to.fullPath == "/loginorregister") {
45 | next();
46 | } else {
47 | next("/loginorregister");
48 | }
49 | }
50 | });
51 | const originalPush = VueRouter.prototype.push;
52 | VueRouter.prototype.push = function push(location, resolve, reject) {
53 | if (resolve || reject) return originalPush.call(this, location, resolve, reject);
54 | return originalPush.call(this, location).catch(err => err);
55 | };
56 | export default router;
57 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/router/router.js:
--------------------------------------------------------------------------------
1 | export const routes = [
2 | {
3 | path: "/admin",
4 | name: "home",
5 | component: () => import("@/views/Admin.vue"),
6 | children: [
7 | {
8 | path: "databoard",
9 | name: "article",
10 | component: () => import("../views/DataBoard.vue"),
11 | },
12 | // {
13 | // path: "article",
14 | // name: "article",
15 | // component: () => import("../views/Article.vue"),
16 | // },
17 | // {
18 | // path: "photo",
19 | // name: "photo",
20 | // component: () => import("../views/Photo.vue"),
21 | // },
22 | // {
23 | // path: "markdown",
24 | // name: "markdown",
25 | // component: () => import("../views/Markdown.vue"),
26 | // },
27 | // {
28 | // path: "timeclue",
29 | // name: "timeclue",
30 | // component: () => import("../views/Timeclue.vue"),
31 | // },
32 | // // {
33 | // // path: "routingmanage",
34 | // // name: "routingmanage",
35 | // // component: () => import("../views/Route.vue"),
36 | // // limits: ["管理员"],
37 | // // },
38 | // {
39 | // path: "user",
40 | // name: "user",
41 | // component: () => import("../views/User.vue"),
42 | // limits: ["管理员"],
43 | // },
44 | // {
45 | // path: "logs",
46 | // name: "logs",
47 | // component: () => import("../views/Log.vue"),
48 | // limits: ["管理员"],
49 | // },
50 | // {
51 | // path: "/admin",
52 | // redirect: "article",
53 | // },
54 | ],
55 | },
56 | {
57 | path: "/loginorregister",
58 | name: "loginorregister",
59 | component: () => import("../views/LoginOrRegister.vue"),
60 | },
61 | {
62 | path: "/",
63 | redirect: "/loginorregister",
64 | },
65 | ];
66 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/store/blogs.js:
--------------------------------------------------------------------------------
1 | import { getBlogs, updateBlog, deleteBlog, getBlog, addBlog, changeBlogState } from "../api/api";
2 | const state = {
3 | blogs: [],
4 | blog: {},
5 | };
6 | const mutations = {
7 | BLOGS(state, blogs) {
8 | state.blogs = blogs;
9 | },
10 | BLOG(state, blog) {
11 | state.blog = blog;
12 | },
13 | };
14 | const actions = {
15 | // 修改文章状态
16 | async changeBlogState({ commit }, _id) {
17 | return await changeBlogState(_id);
18 | },
19 | // 更新文章
20 | async updateBlog({ commit }, data) {
21 | return await updateBlog(data);
22 | },
23 | // 删除文章
24 | async deleteBlog({ commit }, data) {
25 | return await deleteBlog(data);
26 | },
27 | // 获取文章列表
28 | async getBlogs({ commit }) {
29 | let result = await getBlogs();
30 | if (result.status == 200) {
31 | commit("BLOGS", result.data);
32 | } else {
33 | console.log(result);
34 | }
35 | },
36 | // 增加文章
37 | async addBlog({ commit }, data) {
38 | return await addBlog(data);
39 | },
40 | // 获取文章
41 | async getBlog({ commit }, data) {
42 | let result = await getBlog(data);
43 | if (result.status == 200) {
44 | commit("BLOG", result.data);
45 | } else {
46 | return result;
47 | }
48 | },
49 | };
50 | const getters = {
51 | blog(state) {
52 | return state.blog;
53 | },
54 | blogs(state) {
55 | return state.blogs;
56 | },
57 | };
58 | export default {
59 | state,
60 | mutations,
61 | actions,
62 | getters,
63 | };
64 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/store/classify.js:
--------------------------------------------------------------------------------
1 | import { getClassifies, deleteClassify, updateClassifyTitle, addClassify } from "../api/api";
2 | import { setClassifies, getClassifyList } from "../util";
3 | const state = {
4 | classifies: [],
5 | };
6 | const mutations = {
7 | CLASSIFYLIST(state, classifies) {
8 | state.classifies = classifies;
9 | },
10 | };
11 | const actions = {
12 | // 编辑专栏
13 | async updateClassifyTitle({ commit }, data) {
14 | return await updateClassifyTitle(data);
15 | },
16 | //删除专栏
17 | async deleteClassify({ commit }, data) {
18 | return await deleteClassify(data);
19 | },
20 | // 获取专栏列表
21 | async getClassifies({ commit }) {
22 | let result = await getClassifies();
23 | if (result.status == 200) {
24 | commit("CLASSIFYLIST", result.data);
25 | setClassifies(result.data);
26 | } else {
27 | console.log(result);
28 | }
29 | },
30 |
31 | async addClassify({ commit }, data) {
32 | console.log(data);
33 | return await addClassify(data);
34 | },
35 | };
36 | const getters = {
37 | classifies(state) {
38 | return state.classifies;
39 | },
40 | };
41 | export default {
42 | state,
43 | mutations,
44 | actions,
45 | getters,
46 | };
47 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/store/index.js:
--------------------------------------------------------------------------------
1 | // import Vue from "vue";
2 | import Vuex from "vuex";
3 | import user from "./user";
4 | import classify from "./classify";
5 | import article from "./blogs";
6 | import jotting from "./jotting";
7 | import route from "./route";
8 | import tags from "./tags";
9 | Vue.use(Vuex);
10 |
11 | export default new Vuex.Store({
12 | // vuex实现模块化开发,每个模块存放自己的数据
13 | getters: {
14 | routeList: state => state.route.routeList,
15 | },
16 | modules: {
17 | user,
18 | classify,
19 | article,
20 | jotting,
21 | route,
22 | tags,
23 | },
24 | });
25 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/store/jotting.js:
--------------------------------------------------------------------------------
1 | import { getJottings, changeJottingState, deleteJotting, addJotting, getJotting, updateJotting } from "../api/api";
2 | const state = {
3 | jottings: [],
4 | jotting: {},
5 | };
6 | const mutations = {
7 | JOTTINGS(state, jottings) {
8 | state.jottings = jottings;
9 | },
10 | JOTTING(state, jotting) {
11 | state.jotting = jotting;
12 | },
13 | };
14 | const actions = {
15 | // 修改文章状态
16 | async changeJottingState({ commit }, data) {
17 | return await changeJottingState(data);
18 | },
19 | async updateJotting({ commit }, data) {
20 | return await updateJotting(data);
21 | },
22 | // 删除文章
23 | async deleteJotting({ commit }, data) {
24 | return await deleteJotting(data);
25 | },
26 | // 获取文章列表
27 | async getJottings({ commit }) {
28 | let result = await getJottings();
29 | if (result.status == 200) {
30 | commit("JOTTINGS", result.data);
31 | } else {
32 | console.log(result);
33 | }
34 | },
35 | // 添加随笔
36 | async addJotting({ commit }, data) {
37 | return await addJotting(data);
38 | },
39 | // 获取某一随笔
40 | async getJotting({ commit }, data) {
41 | let result = await getJotting(data);
42 | if (result.status == 200) {
43 | commit("JOTTING", result.data);
44 | } else {
45 | console.log(result);
46 | }
47 | },
48 | };
49 | const getters = {
50 | jottings(state) {
51 | return state.jottings;
52 | },
53 | jotting(state) {
54 | return state.jotting;
55 | },
56 | };
57 | export default {
58 | state,
59 | mutations,
60 | actions,
61 | getters,
62 | };
63 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/store/route.js:
--------------------------------------------------------------------------------
1 | import { getRoutes, addSecondRoute, updateRoute, deleteRoute, addFirstRoute, getRouteList } from "../api/api";
2 |
3 | const state = {
4 | routeList: [],
5 | routes: [],
6 | };
7 | const mutations = {
8 | ROUTELIST(state, routeList) {
9 | state.routeList = routeList;
10 | },
11 | ROUTES(state, routes) {
12 | state.routes = routes;
13 | },
14 | CLEARROUTES(state) {
15 | state.routes = [];
16 | },
17 | };
18 | const actions = {
19 | // 新增一级路由
20 | async addFirstRoute({ commit }, route) {
21 | return await addFirstRoute(route);
22 | },
23 | // 新增二级路由
24 | async addSecondRoute({ commit }, route) {
25 | return await addSecondRoute(route);
26 | },
27 | // 更新获取路由信息
28 | async updatRoute({ commit }, data) {
29 | return await updateRoute(data);
30 | },
31 | //删除路由
32 | async deleteRoute({ commit }, data) {
33 | return await deleteRoute(data);
34 | },
35 | // 获取有权限路由列表
36 | async getRoutes({ commit }, role) {
37 | let result = await getRoutes({ role: role });
38 | if (result.status == 200) {
39 | commit("ROUTES", result.data);
40 | } else {
41 | console.log(result);
42 | }
43 | },
44 | // 获取所有路由
45 | async getRouteList({ commit }, role) {
46 | let result = await getRouteList();
47 | if (result.status == 200) {
48 | commit("ROUTELIST", result.data);
49 | } else {
50 | console.log(result);
51 | }
52 | },
53 | // 清空routelist
54 | clearRoutes({ commit }) {
55 | commit("CLEARROUTES");
56 | },
57 | };
58 | // 返回特定路由数据
59 | const getters = {
60 | // 路由管理需要的路由信息和动态导航栏
61 | navRouteList(state) {
62 | const routeList = [];
63 | state.routes.forEach(item => {
64 | if (!item.meta.NotShow && item.name != "日志") {
65 | routeList.push(item);
66 | }
67 | });
68 | return routeList;
69 | },
70 | // 路由拦截需要的路由信息
71 | routes(state) {
72 | const routes = [];
73 | state.routes.forEach(item => {
74 | if (item.name) {
75 | routes.push({
76 | id: item._id,
77 | path: item.path,
78 | name: item.name,
79 | component: item.component,
80 | meta: item.meta,
81 | });
82 | }
83 | });
84 | return routes;
85 | },
86 | };
87 | export default {
88 | state,
89 | mutations,
90 | actions,
91 | getters,
92 | };
93 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/store/tags.js:
--------------------------------------------------------------------------------
1 | import { updateTag, deleteTag, getTags, addTag } from "../api/api";
2 | const state = {
3 | tags: [],
4 | };
5 | const mutations = {
6 | TAGS(state, tags) {
7 | state.tags = tags;
8 | },
9 | };
10 | const actions = {
11 | // 编辑专栏
12 | async updateTag({ commit }, data) {
13 | return await updateTag(data);
14 | },
15 | //删除专栏
16 | async deleteTag({ commit }, data) {
17 | return await deleteTag(data);
18 | },
19 | // 获取专栏列表
20 | async getTags({ commit }) {
21 | let result = await getTags();
22 | console.log(result);
23 | if (result.status == 200) {
24 | commit("TAGS", result.data);
25 | } else {
26 | console.log(result);
27 | }
28 | },
29 |
30 | async addTag({ commit }, data) {
31 | console.log(data);
32 | return await addTag(data);
33 | },
34 | };
35 | const getters = {
36 | tags(state) {
37 | return state.tags;
38 | },
39 | };
40 | export default {
41 | state,
42 | mutations,
43 | actions,
44 | getters,
45 | };
46 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/store/user.js:
--------------------------------------------------------------------------------
1 | import { getUsers, login, deleteUser, register, getUser, updatePassword, logout, updateUserInfo, getMurmurInfos, deleteMurmurInfo } from "../api/api";
2 | import { setToken, getToken, clearToken, setUserInfo, getUserInfo } from "../util";
3 | const state = {
4 | token: getToken() || "",
5 | username: getUserInfo() ? getUserInfo().username : "",
6 | userList: [],
7 | murmurInfos: [],
8 | };
9 | const mutations = {
10 | USERLOGIN(state, token) {
11 | state.token = token;
12 | },
13 | USERINFO(state, info) {
14 | state.info = info;
15 | },
16 | USERLIST(state, userlist) {
17 | state.userList = userlist;
18 | },
19 | MURMURINFOS(state, murmurInfos) {
20 | state.murmurInfos = murmurInfos;
21 | },
22 | //清除本地数据
23 | CLEAR(state) {
24 | state.token = "";
25 | state.info = {};
26 | clearToken();
27 | },
28 | };
29 | const actions = {
30 | // 用户注册
31 | async register({ commit }, user) {
32 | return await register(user);
33 | },
34 | // 用户登录
35 | async login({ commit }, data) {
36 | let result = await login(data);
37 | if (result.status == 200) {
38 | setUserInfo(result.data.user);
39 | setToken(result.data.token);
40 | } else {
41 | return result;
42 | }
43 | },
44 | // 获取用户列表
45 | async getUsers({ commit }) {
46 | let result = await getUsers();
47 | if (result.status == 200) {
48 | commit("USERLIST", result.data);
49 | } else {
50 | console.log(result);
51 | }
52 | },
53 | // 删除用户
54 | async deleteUser({ commit }, data) {
55 | return await deleteUser(data);
56 | },
57 | // 更新用户信息
58 | async updateUserInfo({ commit }, data) {
59 | return await updateUserInfo(data);
60 | },
61 | // 更新密码
62 | async updatePassword({ commit }, data) {
63 | return await updatePassword(data);
64 | },
65 | // 获取用户信息
66 | async getUser({ commit }) {
67 | let result = await getUser();
68 | if (result.status == 200) {
69 | commit("USERINFO", result.data);
70 | } else {
71 | return result;
72 | }
73 | },
74 | async getMurmurInfos({ commit }) {
75 | let result = await getMurmurInfos();
76 | console.log(result, "r");
77 | if (result.status == 200) {
78 | commit("MURMURINFOS", result.data);
79 | } else {
80 | return result;
81 | }
82 | },
83 | async deleteMurmurInfo({ commit }, id) {
84 | return await deleteMurmurInfo(id);
85 | },
86 |
87 | // 退出登录
88 | async logout({ commit }) {
89 | let result = await logout();
90 | if (result.status == 200) {
91 | commit("CLEAR");
92 | } else {
93 | return result;
94 | }
95 | },
96 | };
97 | const getters = {
98 | userList(state) {
99 | return state.userList;
100 | },
101 | token(state) {
102 | return state.token;
103 | },
104 | username(state) {
105 | return state.username;
106 | },
107 | murmurInfos() {
108 | return state.murmurInfos;
109 | },
110 | };
111 | export default {
112 | state,
113 | mutations,
114 | actions,
115 | getters,
116 | };
117 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/util/directive.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import { getUserInfo } from './index';
3 | /**权限指令**/
4 | export const has = Vue.directive('has', {
5 | inserted: function (el, binding, vnode) {
6 | // 获取页面按钮权限
7 | let btnPermissionsArr = [];
8 | if (binding.value) {
9 | // 如果指令传值,获取指令参数,根据指令参数和当前登录人按钮权限做比较。
10 | btnPermissionsArr = Array.of(binding.value);
11 | } else {
12 | // 否则获取路由中的参数,根据路由的btnPermissionsArr和当前登录人按钮权限做比较。
13 | btnPermissionsArr = vnode.context.$route.meta.btnPermissions;
14 | }
15 | if (!Vue.prototype.$_has(btnPermissionsArr)) {
16 | el.parentNode.removeChild(el);
17 | }
18 | }
19 | });
20 | // 权限检查方法
21 | Vue.prototype.$_has = function (value) {
22 | let isExist = false;
23 | // 获取用户按钮权限
24 | let btnPermissionsStr = getUserInfo().role;
25 | if (btnPermissionsStr == undefined || btnPermissionsStr == null) {
26 | return false;
27 | }
28 | if (value.indexOf(btnPermissionsStr) > -1) {
29 | isExist = true;
30 | }
31 | return isExist;
32 | };
33 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/util/index.js:
--------------------------------------------------------------------------------
1 | export const setToken = token => {
2 | sessionStorage.setItem("TOKEN", JSON.stringify(token));
3 | };
4 | export const getToken = () => {
5 | return JSON.parse(sessionStorage.getItem("TOKEN"));
6 | };
7 | // /清除token
8 | export const clearToken = () => {
9 | sessionStorage.removeItem("TOKEN");
10 | sessionStorage.removeItem("userInfo");
11 | };
12 | export const setClassifies = classifies => {
13 | sessionStorage.setItem("CLASSIFIES", JSON.stringify(classifies));
14 | };
15 | export const setUserInfo = user => {
16 | sessionStorage.setItem("userInfo", JSON.stringify(user));
17 | };
18 | export const getUserInfo = () => {
19 | return JSON.parse(sessionStorage.getItem("userInfo"));
20 | };
21 | export const getClassifyList = () => {
22 | return JSON.parse(sessionStorage.getItem("CLASSIFIES"));
23 | };
24 | // 压缩图片
25 | export const pressImg = img => {
26 | // 用于压缩图片的canvas
27 | const canvas = document.createElement('canvas');
28 | const ctx = canvas.getContext('2d');
29 | // 瓦片canvas
30 | const tCanvas = document.createElement('canvas');
31 | const tctx = tCanvas.getContext('2d');
32 | const initSize = img.src.length;
33 | let width = img.width;
34 | let height = img.height;
35 | // 如果图片大于四百万像素,计算压缩比并将大小压至4万以下
36 | let ratio;
37 | if ((ratio = (width * height) / 40000) > 1) {
38 | ratio = Math.sqrt(ratio);
39 | width /= ratio;
40 | height /= ratio;
41 | } else {
42 | ratio = 1;
43 | }
44 | canvas.width = width;
45 | canvas.height = height;
46 | // 铺底色
47 | ctx.fillStyle = '#fff';
48 | ctx.fillRect(0, 0, canvas.width, canvas.height);
49 | // 如果图片像素大于100万则使用瓦片绘制
50 | let count;
51 | if ((count = (width * height) / 10000) > 1) {
52 | count = ~~(Math.sqrt(count) + 1); // 计算要分成多少块瓦片
53 | // 计算每块瓦片的宽和高
54 | const nw = ~~(width / count);
55 | const nh = ~~(height / count);
56 | tCanvas.width = nw;
57 | tCanvas.height = nh;
58 | for (let i = 0; i < count; i++) {
59 | for (let j = 0; j < count; j++) {
60 | tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio * 2, nh * ratio * 2, 0, 0, nw, nh);
61 | ctx.drawImage(tCanvas, i * nw, j * nh, nw * 2, nh * 2);
62 | }
63 | }
64 | } else {
65 | ctx.drawImage(img, 0, 0, width * 2, height * 2);
66 | }
67 | // 进行最小压缩
68 | const pressImgData = canvas.toDataURL('image/jpeg', 0.5);
69 | console.log('压缩前:' + initSize);
70 | console.log('压缩后:' + pressImgData.length);
71 | console.log('压缩率:' + ~~((100 * (initSize - pressImgData.length)) / initSize) + '%');
72 | return pressImgData;
73 | };
74 | // 图片转为二进制
75 | export const toBolb = (basestr, type) => {
76 | const text = window.atob(basestr.split(',')[1]);
77 | const buffer = new ArrayBuffer(text.length);
78 | const ubuffer = new Uint8Array(buffer);
79 | for (let i = 0; i < text.length; i++) {
80 | ubuffer[i] = text.charCodeAt(i);
81 | }
82 | const Builder = window.WebKitBlobBuilder || window.MozBlobBuilder;
83 | let blob;
84 | if (Builder) {
85 | const builder = new Builder();
86 | builder.append(buffer);
87 | blob = builder.getBlob(type);
88 | } else {
89 | blob = new window.Blob([buffer], { type: type });
90 | }
91 | return blob;
92 | };
--------------------------------------------------------------------------------
/MyBlogAdmin/src/views/404.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 返回首页
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/views/Admin.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
18 |
19 |
39 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/views/DataBoard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
182 |
197 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/views/Log.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 | {{ props.row.name }}
11 |
12 |
13 | {{ props.row.shop }}
14 |
15 |
16 | {{ props.row.id }}
17 |
18 |
19 | {{ props.row.shopId }}
20 |
21 |
22 | {{ props.row.category }}
23 |
24 |
25 | {{ props.row.address }}
26 |
27 |
28 | {{ props.row.desc }}
29 |
30 |
31 |
32 |
33 |
37 |
38 |
41 |
42 |
43 |
44 |
45 |
86 |
87 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/views/Result.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 返回
5 |
6 |
7 |
8 |
9 |
23 |
24 |
29 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/views/Self.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 个人中心
5 |
6 | 123
7 | 18100000000
8 | 苏州市
9 |
10 | 学校
11 |
12 | 江苏省苏州市吴中区吴中大道 1188 号
13 |
14 |
15 |
16 |
32 |
33 |
49 |
--------------------------------------------------------------------------------
/MyBlogAdmin/src/views/Timeclue.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 添加节点
4 |
5 |
6 |
7 |
8 |
9 | {{ scope.row.state ? "已完成" : "未完成" }}
10 |
11 |
12 |
13 |
14 | 编辑
15 | {{ scope.row.state ? "未完成" : "已完成" }}
16 | 删除
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
37 |
38 |
39 |
40 |
139 |
--------------------------------------------------------------------------------
/MyBlogAdmin/vue.config.js:
--------------------------------------------------------------------------------
1 | // const CompressionPlugin = require("compression-webpack-plugin"); //引入
2 | module.exports = {
3 | lintOnSave: false,
4 | transpileDependencies: true,
5 | devServer: {
6 | proxy: "http://localhost:3000",
7 | },
8 | productionSourceMap: false,
9 | configureWebpack: {
10 | externals: {
11 | vue: "Vue",
12 | // 'vue-router': 'VueRouter',
13 | // vuex: 'Vuex',
14 | axios: "axios",
15 | "element-ui": "ELEMENT",
16 | },
17 | },
18 | configureWebpack: config => {
19 | // 公共代码抽离
20 | config.optimization = {
21 | splitChunks: {
22 | cacheGroups: {
23 | libs: {
24 | name: "chunk-libs",
25 | test: /[\\/]node_modules[\\/]/,
26 | priority: 10,
27 | chunks: "initial", // only package third parties that are initially dependent
28 | },
29 | common: {
30 | chunks: "all",
31 | test: /[\\/]src[\\/]js[\\/]/,
32 | name: "common",
33 | minChunks: 2,
34 | maxInitialRequests: 5,
35 | minSize: 0,
36 | priority: 60,
37 | },
38 | styles: {
39 | name: "styles",
40 | test: /\.(sa|sc|c)ss$/,
41 | chunks: "all",
42 | enforce: true,
43 | },
44 | pinyin: {
45 | // split pinyin libs
46 | name: "chunk-pinyin",
47 | test: /[\\/]node_modules[\\/]_?pinyin(.*)/,
48 | priority: 40,
49 | chunks: "async",
50 | reuseExistingChunk: true,
51 | },
52 | html2canvas: {
53 | // split html2canvas libs
54 | name: "chunk-html2canvas",
55 | test: /[\\/]node_modules[\\/]_?html2canvas(.*)/,
56 | priority: 40,
57 | chunks: "async",
58 | reuseExistingChunk: true,
59 | },
60 | "vue-pdf": {
61 | // split vue-pdf libs
62 | name: "chunk-vue-pdf",
63 | test: /[\\/]node_modules[\\/]_?vue-pdf(.*)/,
64 | priority: 40,
65 | chunks: "async",
66 | reuseExistingChunk: true,
67 | },
68 | runtimeChunk: {
69 | name: "manifest",
70 | },
71 | },
72 | },
73 | };
74 | },
75 | // configureWebpack: config => {
76 | // if (process.env.NODE_ENV === "production") {
77 | // config.plugins.push(
78 | // new CompressionPlugin({
79 | // algorithm: "gzip",
80 | // test: /\.js$|\.html$|\.css$|\.jpg$|\.png/,
81 | // threshold: 10240,
82 | // minRatio: 0.5,
83 | // // deleteOriginalAssets: true, // 是否删除源文件
84 | // })
85 | // );
86 | // }
87 | // },
88 | };
89 |
--------------------------------------------------------------------------------
/MyBlogFront/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/MyBlogFront/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | 'extends': [
7 | 'plugin:vue/essential',
8 | 'eslint:recommended'
9 | ],
10 | parserOptions: {
11 | parser: '@babel/eslint-parser'
12 | },
13 | rules: {
14 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
15 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/MyBlogFront/babel.config.js:
--------------------------------------------------------------------------------
1 | const proPlugins = [];
2 | if (process.env.NODE_ENV === 'production') {
3 | proPlugins.push('transform-remove-console');
4 | }
5 | module.exports = {
6 | presets: ['@vue/cli-plugin-babel/preset'],
7 | plugins: [...proPlugins],
8 | };
9 |
--------------------------------------------------------------------------------
/MyBlogFront/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "esnext",
5 | "baseUrl": "./",
6 | "moduleResolution": "node",
7 | "paths": {
8 | "@/*": [
9 | "src/*"
10 | ]
11 | },
12 | "lib": [
13 | "esnext",
14 | "dom",
15 | "dom.iterable",
16 | "scripthost"
17 | ]
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/MyBlogFront/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "myblogfront",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint",
9 | "report": "vue-cli-service build --report"
10 | },
11 | "dependencies": {
12 | "axios": "^0.27.2",
13 | "core-js": "^3.8.3",
14 | "fingerprintjs2": "^2.1.4",
15 | "mavon-editor": "^2.10.4",
16 | "vue": "^2.6.14",
17 | "vue-router": "^3.5.1",
18 | "vuex": "^3.6.2"
19 | },
20 | "devDependencies": {
21 | "@babel/core": "^7.12.16",
22 | "@babel/eslint-parser": "^7.12.16",
23 | "@vue/cli-plugin-babel": "~5.0.0",
24 | "@vue/cli-plugin-eslint": "~5.0.0",
25 | "@vue/cli-plugin-router": "~5.0.0",
26 | "@vue/cli-plugin-vuex": "~5.0.0",
27 | "@vue/cli-service": "~5.0.0",
28 | "babel-plugin-transform-remove-console": "^6.9.4",
29 | "compression-webpack-plugin": "^10.0.0",
30 | "element-ui": "^2.15.9",
31 | "eslint": "^8.23.0",
32 | "eslint-plugin-vue": "^8.0.3",
33 | "image-webpack-loader": "^8.1.0",
34 | "less": "^4.0.0",
35 | "less-loader": "^8.0.0",
36 | "vue-template-compiler": "^2.6.14"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/MyBlogFront/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogFront/public/favicon.ico
--------------------------------------------------------------------------------
/MyBlogFront/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | 孤城浪人的博客
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
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 |
--------------------------------------------------------------------------------
/MyBlogFront/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
57 |
111 |
--------------------------------------------------------------------------------
/MyBlogFront/src/api/api.js:
--------------------------------------------------------------------------------
1 | // 统一管理所有接口
2 | import requests from './request';
3 | // 获取文章列表
4 | export const getPublishBlogs = params => requests.get('/blogs/getpublishblogs', { params });
5 |
6 | // 获取某一文章
7 | export const getBlog = params => requests.get('/blogs/getblog', { params });
8 |
9 | // 获取专栏列表
10 | export const getClassifies = () => requests.get('/classifies/getclassifies');
11 |
12 | // 获取随笔
13 | export const getPublishJottings = params =>
14 | requests.get('/jottings/getpublishjottings', { params });
15 |
16 | // 获取随笔
17 | export const getJotting = params => requests.get('/jottings/getjotting', { params });
18 |
19 | // 获取文章总数信息
20 | export const getWebInfo = () => requests.get('/synthesis/getwebinfo');
21 |
22 | // 获取某书签所有博客信息
23 | export const getBlogsOfClassify = params => requests.get('/blogs/getblogsofclassify', { params });
24 |
25 | // 博客点赞
26 | export const giveBlogALike = params => requests.get('/blogs/addfavour', { params });
27 |
28 | // 随笔点赞
29 | export const giveJottingALike = params => requests.get('/jottings/addfavour', { params });
30 |
31 | // 增加博客浏览量
32 | export const addBlogBrowse = params => requests.get('/blogs/addblogbrowse', { params });
33 | // 增加随笔浏览量
34 | export const addJottingBrowse = params => requests.get('/jottings/addjottingbrowse', { params });
35 |
36 | // 获取右边信息栏基础信息
37 | export const getSliderInfo = () => requests.get('/synthesis/getsliderinfo');
38 | // 搜索
39 | export const search = params => requests.get('/synthesis/searcharticle', { params });
40 | // 新增murmur
41 | export const addMurmur = data => requests.post('/murmur/addmurmurinfo', data);
42 | // 修改murmur
43 | export const updateMurmur = data => requests.post('/murmur/updatemurmurusername', data);
44 |
45 | // 获取某篇文章的所有评论
46 | export const getCommentsOfArticle = params =>
47 | requests.get('/comments/getcommentsofarticle', { params });
48 | // 一级评论点赞
49 | export const addfirstfavour = params => requests.get('/comments/addfirstfavour', { params });
50 | // 二级评论点赞
51 | export const addsecondfavour = params => requests.get('/comments/addsecondfavour', { params });
52 | // 新增一级评论
53 | export const addfirstcomment = data => requests.post('/comments/addfirstcomment', data);
54 | // 新增二级评论
55 | export const addsecondcomment = data => requests.post('/comments/addsecondcomment', data);
56 | // 删除一级评论
57 | export const deletefirstcomment = params =>
58 | requests.delete('/comments/deletefirstcomment', { params });
59 | // 删除二级评论
60 | export const deletesecondcomment = params =>
61 | requests.delete('/comments/deletesecondcomment', { params });
62 | // 获取时间线数据
63 | export const getTimeclues = params => requests.get('/timeclues/gettimeclues', { params });
64 | // 获取照片墙线数据
65 | export const getPhotos = () => requests.get('/photo/getphotos');
66 | // 根据标签获取文章
67 | export const getArticlesOfTag = params => requests.get('/synthesis/getarticlesoftag', { params });
68 | // 上传图片
69 | export const uploadAvatar = data =>
70 | requests.post('/synthesis/uploadavatar', data, {
71 | headers: { 'content-type': 'multipart/form-data' },
72 | });
73 |
--------------------------------------------------------------------------------
/MyBlogFront/src/api/index.js:
--------------------------------------------------------------------------------
1 | //导入所有接口
2 | import * as api from './api'
3 |
4 | const install = Vue => {
5 | if (install.installed) return;
6 |
7 | install.installed = true;
8 |
9 | Object.defineProperties(Vue.prototype, {
10 | //此处挂载在 Vue 原型的 $api 对象上
11 | $api: {
12 | get() {
13 | return api
14 | }
15 | }
16 | })
17 | }
18 |
19 | export default install
--------------------------------------------------------------------------------
/MyBlogFront/src/api/request.js:
--------------------------------------------------------------------------------
1 | // 引入axios进行二次封装
2 | // import axios from 'axios';
3 | const requests = axios.create({
4 | // 配置对象
5 | // 基础路径
6 | baseURL: '/api',
7 | // 请求超时的时间限 制
8 | timeout: 5000,
9 | });
10 | // 请求拦截器:在请求发出去之前做处理
11 | requests.interceptors.request.use(config => {
12 | // config:配置对象,对象信息里边有一个重要信息,请求头headers
13 | // 进度条开始
14 | return config;
15 | });
16 | // 响应拦截器
17 | requests.interceptors.response.use(
18 | res => {
19 | // 进度条结束
20 | return res.data;
21 | },
22 | err => {
23 | if (err.code === 'ECONNABORTED' && err.message.indexOf('timeout') !== -1) {
24 | return Promise.reject('timeout请求超时');
25 | // return service.request(originalRequest);// 再重复请求一次
26 | }
27 | if (err.message.indexOf('Network') !== -1) {
28 | return Promise.reject('网络异常');
29 | }
30 | if (err.response && err.response.status === 404) {
31 | return Promise.reject('请求的资源无法找到');
32 | } else if (err.response && err.response.status === 500) {
33 | return Promise.reject('服务器繁忙');
34 | }
35 | return err;
36 | }
37 | );
38 |
39 | export default requests;
40 |
--------------------------------------------------------------------------------
/MyBlogFront/src/assets/common.css:
--------------------------------------------------------------------------------
1 | /* 分页样式 */
2 | .pagination {
3 | float: right;
4 | margin-bottom: 2vh;
5 | }
6 | /* 空状态 */
7 | .el-empty__description p {
8 | color: #000;
9 | }
10 | .el-icon-search {
11 | margin-right: 10px;
12 | }
13 | .el-input__inner {
14 | transition: 0.6s;
15 | border: none;
16 | }
17 | ::-webkit-scrollbar {
18 | /*滚动条整体样式*/
19 | width: 5px;
20 | }
21 |
22 | ::-webkit-scrollbar-thumb {
23 | /*滚动条里面小方块*/
24 | border-radius: 5px;
25 | background: rgba(0, 0, 0, 0.2);
26 | }
27 |
28 | ::-webkit-scrollbar-track {
29 | /*滚动条里面轨道*/
30 | border-radius: 0;
31 | background: rgba(0, 0, 0, 0);
32 | }
33 | /* hover效果 */
34 | .card:hover {
35 | transition: 0.5s;
36 | box-shadow: 0px 9.7px 2.2px rgba(80, 80, 80, 0.134), 0px 11.6px 5.3px rgba(80, 80, 80, 0.184),
37 | 0px 12.4px 10px rgba(80, 80, 80, 0.193), 0px 13px 17.9px rgba(80, 80, 80, 0.218),
38 | 0px 13.7px 33.4px rgba(80, 80, 80, 0.309), 0px 15px 80px rgba(80, 80, 80, 0.5);
39 | }
40 |
--------------------------------------------------------------------------------
/MyBlogFront/src/assets/icons/iconfont.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: "iconfont"; /* Project id 3179613 */
3 | src: url('iconfont.woff2?t=1656420527418') format('woff2'),
4 | url('iconfont.woff?t=1656420527418') format('woff'),
5 | url('iconfont.ttf?t=1656420527418') format('truetype');
6 | }
7 |
8 | .iconfont {
9 | font-family: "iconfont" !important;
10 | font-size: 16px;
11 | font-style: normal;
12 | -webkit-font-smoothing: antialiased;
13 | -moz-osx-font-smoothing: grayscale;
14 | }
15 |
16 | .icon-icon:before {
17 | content: "\e651";
18 | }
19 |
20 | .icon-rili:before {
21 | content: "\e602";
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/MyBlogFront/src/assets/icons/iconfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogFront/src/assets/icons/iconfont.ttf
--------------------------------------------------------------------------------
/MyBlogFront/src/assets/icons/iconfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogFront/src/assets/icons/iconfont.woff
--------------------------------------------------------------------------------
/MyBlogFront/src/assets/icons/iconfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogFront/src/assets/icons/iconfont.woff2
--------------------------------------------------------------------------------
/MyBlogFront/src/assets/img/avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogFront/src/assets/img/avatar.png
--------------------------------------------------------------------------------
/MyBlogFront/src/assets/img/infoBg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogFront/src/assets/img/infoBg.jpg
--------------------------------------------------------------------------------
/MyBlogFront/src/assets/img/lightBg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogFront/src/assets/img/lightBg.png
--------------------------------------------------------------------------------
/MyBlogFront/src/assets/img/nightBg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogFront/src/assets/img/nightBg.jpg
--------------------------------------------------------------------------------
/MyBlogFront/src/assets/img/slideBg/slidebg1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogFront/src/assets/img/slideBg/slidebg1.jpg
--------------------------------------------------------------------------------
/MyBlogFront/src/assets/img/slideBg/slidebg2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogFront/src/assets/img/slideBg/slidebg2.jpg
--------------------------------------------------------------------------------
/MyBlogFront/src/assets/img/slideBg/slidebg3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogFront/src/assets/img/slideBg/slidebg3.jpg
--------------------------------------------------------------------------------
/MyBlogFront/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogFront/src/assets/logo.png
--------------------------------------------------------------------------------
/MyBlogFront/src/components/Footer.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
13 |
14 |
24 |
--------------------------------------------------------------------------------
/MyBlogFront/src/components/Header.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
45 |
83 |
--------------------------------------------------------------------------------
/MyBlogFront/src/components/Loading/Loading.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
{{ text }}
15 |
16 |
17 |
18 |
26 |
27 |
124 |
--------------------------------------------------------------------------------
/MyBlogFront/src/components/Loading/index.js:
--------------------------------------------------------------------------------
1 | import loadingComponent from '@/components/Loading/Loading.vue';
2 | // import Vue from 'vue';
3 | const LoadingConstructor = Vue.extend(loadingComponent);
4 |
5 | const instance = new LoadingConstructor({
6 | el: document.createElement('div'),
7 | });
8 |
9 | instance.show = false; // 默认隐藏
10 | const loading = {
11 | show(text) {
12 | // 显示方法
13 | instance.show = true;
14 | instance.text = text;
15 | document.body.appendChild(instance.$el);
16 | },
17 | hide() {
18 | // 隐藏方法
19 | instance.show = false;
20 | },
21 | };
22 |
23 | export default {
24 | install() {
25 | if (!Vue.$loading) {
26 | Vue.$loading = loading;
27 | }
28 | Vue.mixin({
29 | created() {
30 | this.$loading = Vue.$loading;
31 | },
32 | });
33 | },
34 | };
35 |
--------------------------------------------------------------------------------
/MyBlogFront/src/components/Nav.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
14 | 博客
15 |
16 |
17 | 心情
18 |
19 |
20 | 照片墙
21 |
22 |
23 | 留言板
24 |
25 |
26 | 时间线
27 |
28 |
29 | 关于
30 |
31 |
32 |
33 |
34 |
35 |
36 |
64 |
65 |
99 |
--------------------------------------------------------------------------------
/MyBlogFront/src/components/Slideshow.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
13 |
14 |
![avatar]()
15 |
16 |
孤城浪人
17 |
18 |
19 | 博客{{ webInfo.blogNums || 0 }}
20 |
21 |
22 | 心情{{ webInfo.jottingNums || 0 }}
23 |
24 |
25 | 专栏{{ webInfo.classifyNums || 0 }}
26 |
27 |
28 | 标签{{ webInfo.tagNums || 0 }}
29 |
30 |
31 |
32 |
欢迎来到我的小站!
33 |
34 |
35 |
80 |
81 |
162 |
--------------------------------------------------------------------------------
/MyBlogFront/src/main.js:
--------------------------------------------------------------------------------
1 | // import Vue from 'vue';
2 | import App from './App.vue';
3 | import router from './router';
4 | import store from '@/store';
5 | import '@/assets/icons/iconfont.css';
6 | import '@/assets/common.css';
7 | import api from '@/api';
8 | // import ElementUI from 'element-ui';
9 |
10 | // 应用封装的loading
11 | import Loading from '@/components/Loading/index';
12 | // import 'element-ui/lib/theme-chalk/index.css';
13 | // Vue.prototype.$ELEMENT = { size: 'small', zIndex: 3000 };
14 | Vue.use(Loading);
15 | // Vue.use(ElementUI);
16 | Vue.config.productionTip = false;
17 | Vue.use(api);
18 | new Vue({
19 | router,
20 | store,
21 | render: h => h(App),
22 | }).$mount('#app');
23 |
--------------------------------------------------------------------------------
/MyBlogFront/src/router/index.js:
--------------------------------------------------------------------------------
1 | // import Vue from 'vue';
2 | import VueRouter from 'vue-router';
3 |
4 | Vue.use(VueRouter);
5 |
6 | const routes = [
7 | {
8 | path: '/list/:type',
9 | component: () => import('@/views/List.vue'),
10 | },
11 | {
12 | path: '/about',
13 | component: () => import('@/views/About.vue'),
14 | },
15 | {
16 | path: '/article/:type/:id',
17 | component: () => import('@/views/Article.vue'),
18 | },
19 |
20 | {
21 | path: '/timeclue',
22 | component: () => import('@/views/TimeClue.vue'),
23 | },
24 | {
25 | path: '/messageboard',
26 | component: () => import('@/views/MessageBoard.vue'),
27 | },
28 | {
29 | path: '/photo',
30 | component: () => import('@/views/PhotoWall.vue'),
31 | },
32 | {
33 | path: '/',
34 | redirect: '/list/blog',
35 | },
36 | {
37 | path: '*',
38 | redirect: '/list/blog',
39 | },
40 | ];
41 |
42 | const router = new VueRouter({
43 | mode: 'history',
44 | base: process.env.BASE_URL,
45 | routes,
46 | scrollBehavior: (to, from, savePosition) => {
47 | // 动行为,每个页面切换时自动回到顶部
48 | if (savePosition) {
49 | return {
50 | savePosition,
51 | behavior: 'smooth', // // return 期望滚动到哪个的位置
52 | };
53 | } else {
54 | return { behavior: 'smooth', y: 0 };
55 | }
56 | },
57 | });
58 | // 重定向不报错
59 | const routerPush = VueRouter.prototype.push;
60 | VueRouter.prototype.push = function push(location) {
61 | return routerPush.call(this, location).catch(error => error);
62 | };
63 | export default router;
64 |
--------------------------------------------------------------------------------
/MyBlogFront/src/store/index.js:
--------------------------------------------------------------------------------
1 | // import Vue from 'vue';
2 | import Vuex from 'vuex';
3 | import synthesis from './synthesis';
4 | import theme from './theme';
5 |
6 | Vue.use(Vuex);
7 |
8 | export default new Vuex.Store({
9 | // vuex实现模块化开发,每个模块存放自己的数据
10 | modules: {
11 | synthesis,
12 | theme,
13 | },
14 | });
15 |
--------------------------------------------------------------------------------
/MyBlogFront/src/store/synthesis.js:
--------------------------------------------------------------------------------
1 | const state = {
2 | blogs: [],
3 | jottings: [],
4 | blogsOfClassify: [],
5 | classifies: [],
6 | searchs: [],
7 | };
8 | const getters = {};
9 | const mutations = {
10 | SAVEBLOG(state, blogs) {
11 | state.blogs = blogs;
12 | },
13 | SAVEJOTTING(state, jottings) {
14 | state.jottings = jottings;
15 | },
16 | SAVEBLOGSOFCLASSIFY(state, blogsOfClassify) {
17 | state.blogsOfClassify = blogsOfClassify;
18 | },
19 | SAVECLASSIFIES(state, classifies) {
20 | state.classifies = classifies;
21 | },
22 | SAVESEARCHLIST(state, searchs) {
23 | state.searchs = searchs;
24 | },
25 | };
26 | const actions = {};
27 |
28 | export default {
29 | state,
30 | mutations,
31 | actions,
32 | getters,
33 | };
34 |
--------------------------------------------------------------------------------
/MyBlogFront/src/store/theme.js:
--------------------------------------------------------------------------------
1 | const state = {
2 | isLight: true,
3 | color: '#FFFFFF',
4 | infoBgColor: 'rgba(255,255,255,0.6)',
5 | mainBg: 'rgba(50,50,50,0.6)',
6 | cardBg: 'rgb(100,100,100)',
7 | animateBg: '#0088b5',
8 | headFootBg: '#545c64',
9 | };
10 | const getters = {
11 | color(state) {
12 | if (state.isLight) {
13 | state.color = '#000000';
14 | } else {
15 | state.color = '#dddddd';
16 | }
17 | return 'color:' + state.color;
18 | },
19 | infoBgColor(state) {
20 | if (state.isLight) {
21 | state.infoBgColor = 'rgba(255,255,255,0.6)';
22 | } else {
23 | state.infoBgColor = 'rgba(0,0,0,0.6)';
24 | }
25 | return 'background-color:' + state.infoBgColor;
26 | },
27 | mainBg(state) {
28 | if (state.isLight) {
29 | state.mainBg = 'rgba(255,255,255,0.6)';
30 | } else {
31 | state.mainBg = 'rgba(50,50,50,0.6)';
32 | }
33 | return 'background-color:' + state.mainBg;
34 | },
35 | cardBg(state) {
36 | if (state.isLight) {
37 | state.cardBg = '#ffffff';
38 | } else {
39 | state.cardBg = '#323232';
40 | }
41 | return 'background-color:' + state.cardBg;
42 | },
43 | specialcardBg(state) {
44 | if (state.isLight) {
45 | state.cardBg = '#ffffff';
46 | } else {
47 | state.cardBg = '#323232';
48 | }
49 | return state.cardBg;
50 | },
51 | animateBg(state) {
52 | if (state.isLight) {
53 | state.animateBg = '#0088b5';
54 | } else {
55 | state.animateBg = '#777777';
56 | }
57 | return 'background-color:' + state.animateBg;
58 | },
59 | headFootBg(state) {
60 | if (state.isLight) {
61 | state.headFootBg = 'rgb(130, 130, 130)';
62 | } else {
63 | state.headFootBg = 'rgb(50, 50, 50)';
64 | }
65 | return 'background-color:' + state.headFootBg;
66 | },
67 | };
68 | const mutations = {
69 | CHANGETHEME(state) {
70 | state.isLight = !state.isLight;
71 | },
72 | };
73 |
74 | const actions = {};
75 |
76 | export default {
77 | state,
78 | mutations,
79 | actions,
80 | getters,
81 | };
82 |
--------------------------------------------------------------------------------
/MyBlogFront/src/util/bgSpecialEffect.js:
--------------------------------------------------------------------------------
1 | export default () => {
2 | const flakes = [];
3 | const canvas = document.createElement('canvas');
4 | document.body.appendChild(canvas);
5 | const ctx = canvas.getContext('2d');
6 | canvas.setAttribute(
7 | 'style',
8 | ' top: 0; left: 0; z-index: 99999; position: fixed; pointer-events: none;'
9 | );
10 | const flakeCount = 50;
11 | let mX = -100;
12 | let mY = -100;
13 | canvas.width = window.innerWidth;
14 | canvas.height = window.innerHeight;
15 | function snow() {
16 | ctx.clearRect(0, 0, canvas.width, canvas.height);
17 |
18 | for (let i = 0; i < flakeCount; i++) {
19 | const flake = flakes[i],
20 | x = mX,
21 | y = mY,
22 | minDist = 150,
23 | x2 = flake.x,
24 | y2 = flake.y;
25 |
26 | const dist = Math.sqrt((x2 - x) * (x2 - x) + (y2 - y) * (y2 - y));
27 | // (dx = x2 - x), (dy = y2 - y);
28 |
29 | if (dist < minDist) {
30 | const force = minDist / (dist * dist),
31 | xcomp = (x - x2) / dist,
32 | ycomp = (y - y2) / dist,
33 | deltaV = force / 2;
34 |
35 | flake.velX -= deltaV * xcomp;
36 | flake.velY -= deltaV * ycomp;
37 | } else {
38 | flake.velX *= 0.98;
39 | if (flake.velY <= flake.speed) {
40 | flake.velY = flake.speed;
41 | }
42 | flake.velX += Math.cos((flake.step += 0.05)) * flake.stepSize;
43 | }
44 |
45 | ctx.fillStyle = 'rgba(255,255,255,' + flake.opacity + ')';
46 | flake.y += flake.velY;
47 | flake.x += flake.velX;
48 |
49 | if (flake.y >= canvas.height || flake.y <= 0) {
50 | reset(flake);
51 | }
52 |
53 | if (flake.x >= canvas.width || flake.x <= 0) {
54 | reset(flake);
55 | }
56 |
57 | ctx.beginPath();
58 | ctx.arc(flake.x, flake.y, flake.size, 0, Math.PI * 2);
59 | ctx.fill();
60 | }
61 | requestAnimationFrame(snow);
62 | }
63 |
64 | function reset(flake) {
65 | flake.x = Math.floor(Math.random() * canvas.width);
66 | flake.y = 0;
67 | flake.size = Math.random() * 3 + 2;
68 | flake.speed = Math.random() * 1 + 0.5;
69 | flake.velY = flake.speed;
70 | flake.velX = 0;
71 | flake.opacity = Math.random() * 0.5 + 0.3;
72 | }
73 |
74 | function init() {
75 | for (let i = 0; i < flakeCount; i++) {
76 | let x = Math.floor(Math.random() * canvas.width),
77 | y = Math.floor(Math.random() * canvas.height),
78 | size = Math.random() * 3 + 2,
79 | speed = Math.random() * 1 + 0.5,
80 | opacity = Math.random() * 0.5 + 0.3;
81 |
82 | flakes.push({
83 | speed: speed,
84 | velY: speed,
85 | velX: 0,
86 | x: x,
87 | y: y,
88 | size: size,
89 | stepSize: (Math.random() / 30) * 1,
90 | step: 0,
91 | angle: 180,
92 | opacity: opacity,
93 | });
94 | }
95 |
96 | snow();
97 | }
98 |
99 | document.addEventListener('mousemove', function (e) {
100 | mX = e.clientX;
101 | mY = e.clientY;
102 | });
103 | window.addEventListener('resize', function () {
104 | canvas.width = window.innerWidth;
105 | canvas.height = window.innerHeight;
106 | });
107 | init();
108 | };
109 |
--------------------------------------------------------------------------------
/MyBlogFront/src/util/clickSpecialEffect.js:
--------------------------------------------------------------------------------
1 | export default () => {
2 | let balls = [];
3 | let longPressed = false;
4 | let longPress;
5 | let multiplier = 0;
6 | let width, height;
7 | let origin;
8 | let normal;
9 | let ctx;
10 | const colours = ['#F73859', '#14FFEC', '#00E0FF', '#FF99FE', '#FAF15D'];
11 | const canvas = document.createElement('canvas');
12 | document.body.appendChild(canvas);
13 | canvas.setAttribute(
14 | 'style',
15 | 'width: 100%; height: 100%; top: 0; left: 0; z-index: 99999; position: fixed; pointer-events: none;'
16 | );
17 | const pointer = document.createElement('span');
18 | pointer.classList.add('pointer');
19 | document.body.appendChild(pointer);
20 |
21 | if (canvas.getContext && window.addEventListener) {
22 | ctx = canvas.getContext('2d');
23 | updateSize();
24 | window.addEventListener('resize', updateSize, false);
25 | loop();
26 | window.addEventListener(
27 | 'mousedown',
28 | function (e) {
29 | pushBalls(randBetween(10, 20), e.clientX, e.clientY);
30 | document.body.classList.add('is-pressed');
31 | longPress = setTimeout(function () {
32 | document.body.classList.add('is-longpress');
33 | longPressed = true;
34 | }, 500);
35 | },
36 | false
37 | );
38 | window.addEventListener(
39 | 'mouseup',
40 | function (e) {
41 | clearInterval(longPress);
42 | if (longPressed == true) {
43 | document.body.classList.remove('is-longpress');
44 | pushBalls(
45 | randBetween(50 + Math.ceil(multiplier), 100 + Math.ceil(multiplier)),
46 | e.clientX,
47 | e.clientY
48 | );
49 | longPressed = false;
50 | }
51 | document.body.classList.remove('is-pressed');
52 | },
53 | false
54 | );
55 | window.addEventListener(
56 | 'mousemove',
57 | function (e) {
58 | let x = e.clientX;
59 | let y = e.clientY;
60 | pointer.style.top = y + 'px';
61 | pointer.style.left = x + 'px';
62 | },
63 | false
64 | );
65 | } else {
66 | console.log('canvas or addEventListener is unsupported!');
67 | }
68 |
69 | function updateSize() {
70 | canvas.width = window.innerWidth * 2;
71 | canvas.height = window.innerHeight * 2;
72 | canvas.style.width = window.innerWidth + 'px';
73 | canvas.style.height = window.innerHeight + 'px';
74 | ctx.scale(2, 2);
75 | width = canvas.width = window.innerWidth;
76 | height = canvas.height = window.innerHeight;
77 | origin = {
78 | x: width / 2,
79 | y: height / 2,
80 | };
81 | normal = {
82 | x: width / 2,
83 | y: height / 2,
84 | };
85 | }
86 | class Ball {
87 | constructor(x = origin.x, y = origin.y) {
88 | this.x = x;
89 | this.y = y;
90 | this.angle = Math.PI * 2 * Math.random();
91 | if (longPressed == true) {
92 | this.multiplier = randBetween(14 + multiplier, 15 + multiplier);
93 | } else {
94 | this.multiplier = randBetween(6, 12);
95 | }
96 | this.vx = (this.multiplier + Math.random() * 0.5) * Math.cos(this.angle);
97 | this.vy = (this.multiplier + Math.random() * 0.5) * Math.sin(this.angle);
98 | this.r = randBetween(8, 12) + 3 * Math.random();
99 | this.color = colours[Math.floor(Math.random() * colours.length)];
100 | }
101 | update() {
102 | this.x += this.vx - normal.x;
103 | this.y += this.vy - normal.y;
104 | normal.x = (-2 / window.innerWidth) * Math.sin(this.angle);
105 | normal.y = (-2 / window.innerHeight) * Math.cos(this.angle);
106 | this.r -= 0.3;
107 | this.vx *= 0.9;
108 | this.vy *= 0.9;
109 | }
110 | }
111 |
112 | function pushBalls(count = 1, x = origin.x, y = origin.y) {
113 | for (let i = 0; i < count; i++) {
114 | balls.push(new Ball(x, y));
115 | }
116 | }
117 |
118 | function randBetween(min, max) {
119 | return Math.floor(Math.random() * max) + min;
120 | }
121 |
122 | function loop() {
123 | ctx.fillStyle = 'rgba(255, 255, 255, 0)';
124 | ctx.clearRect(0, 0, canvas.width, canvas.height);
125 | for (let i = 0; i < balls.length; i++) {
126 | let b = balls[i];
127 | if (b.r < 0) continue;
128 | ctx.fillStyle = b.color;
129 | ctx.beginPath();
130 | ctx.arc(b.x, b.y, b.r, 0, Math.PI * 2, false);
131 | ctx.fill();
132 | b.update();
133 | }
134 | if (longPressed == true) {
135 | multiplier += 0.2;
136 | } else if (!longPressed && multiplier >= 0) {
137 | multiplier -= 0.4;
138 | }
139 | removeBall();
140 | requestAnimationFrame(loop);
141 | }
142 |
143 | function removeBall() {
144 | for (let i = 0; i < balls.length; i++) {
145 | let b = balls[i];
146 | if (b.x + b.r < 0 || b.x - b.r > width || b.y + b.r < 0 || b.y - b.r > height || b.r < 0) {
147 | balls.splice(i, 1);
148 | }
149 | }
150 | }
151 | };
152 |
--------------------------------------------------------------------------------
/MyBlogFront/src/util/index.js:
--------------------------------------------------------------------------------
1 | import Fingerprint2 from 'fingerprintjs2';
2 | // 获取浏览器指纹
3 | export const createFingerprint = () => {
4 | Fingerprint2.get(components => {
5 | const values = components.map((component, index) => {
6 | if (index === 0) {
7 | //把微信浏览器里UA的wifi或4G等网络替换成空,不然切换网络会ID不一样
8 | return component.value.replace(/\bNetType\/\w+\b/, '');
9 | }
10 | return component.value;
11 | });
12 | // 生成最终id murmur
13 | let murmur = Fingerprint2.x64hash128(values.join(''), 31);
14 | localStorage.setItem('browserId', murmur); // 存储浏览器指纹,在项目中用于校验用户身份和埋点
15 | });
16 | };
17 | // 压缩图片
18 | export const pressImg = img => {
19 | // 用于压缩图片的canvas
20 | const canvas = document.createElement('canvas');
21 | const ctx = canvas.getContext('2d');
22 | // 瓦片canvas
23 | const tCanvas = document.createElement('canvas');
24 | const tctx = tCanvas.getContext('2d');
25 | // const initSize = img.src.length;
26 | let width = img.width;
27 | let height = img.height;
28 | // 如果图片大于四百万像素,计算压缩比并将大小压至4万以下
29 | let ratio;
30 | if ((ratio = (width * height) / 40000) > 1) {
31 | ratio = Math.sqrt(ratio);
32 | width /= ratio;
33 | height /= ratio;
34 | } else {
35 | ratio = 1;
36 | }
37 | canvas.width = width;
38 | canvas.height = height;
39 | // 铺底色
40 | ctx.fillStyle = '#fff';
41 | ctx.fillRect(0, 0, canvas.width, canvas.height);
42 | // 如果图片像素大于100万则使用瓦片绘制
43 | let count;
44 | if ((count = (width * height) / 10000) > 1) {
45 | count = ~~(Math.sqrt(count) + 1); // 计算要分成多少块瓦片
46 | // 计算每块瓦片的宽和高
47 | const nw = ~~(width / count);
48 | const nh = ~~(height / count);
49 | tCanvas.width = nw;
50 | tCanvas.height = nh;
51 | for (let i = 0; i < count; i++) {
52 | for (let j = 0; j < count; j++) {
53 | tctx.drawImage(
54 | img,
55 | i * nw * ratio,
56 | j * nh * ratio,
57 | nw * ratio * 2,
58 | nh * ratio * 2,
59 | 0,
60 | 0,
61 | nw,
62 | nh
63 | );
64 | ctx.drawImage(tCanvas, i * nw, j * nh, nw * 2, nh * 2);
65 | }
66 | }
67 | } else {
68 | ctx.drawImage(img, 0, 0, width * 2, height * 2);
69 | }
70 | // 进行最小压缩
71 | const pressImgData = canvas.toDataURL('image/jpeg', 0.5);
72 | // console.log('压缩前:' + initSize);
73 | // console.log('压缩后:' + pressImgData.length);
74 | // console.log('压缩率:' + ~~((100 * (initSize - pressImgData.length)) / initSize) + '%');
75 | return pressImgData;
76 | };
77 | // 图片转为二进制
78 | export const toBolb = (basestr, type) => {
79 | const text = window.atob(basestr.split(',')[1]);
80 | const buffer = new ArrayBuffer(text.length);
81 | const ubuffer = new Uint8Array(buffer);
82 | for (let i = 0; i < text.length; i++) {
83 | ubuffer[i] = text.charCodeAt(i);
84 | }
85 | const Builder = window.WebKitBlobBuilder || window.MozBlobBuilder;
86 | let blob;
87 | if (Builder) {
88 | const builder = new Builder();
89 | builder.append(buffer);
90 | blob = builder.getBlob(type);
91 | } else {
92 | blob = new window.Blob([buffer], { type: type });
93 | }
94 | return blob;
95 | };
96 | // 头像更新后递归修改评论头像
97 | export const deepCommentAvatar = (murmur, avatarUrl, comments) => {
98 | comments.forEach(item => {
99 | if (murmur == item.murmur) {
100 | item.avatarUrl = avatarUrl;
101 | }
102 | if (item.replyInfo?.length > 0) {
103 | deepCommentAvatar(murmur, avatarUrl, item.replyInfo);
104 | }
105 | });
106 | };
107 |
--------------------------------------------------------------------------------
/MyBlogFront/src/views/About.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |

5 |
6 |
7 |
WPF 男 在校大学生(即将毕业啦!)
8 |
喜欢运动、羽毛球,乒乓球和篮球也会一点,足球也玩过
9 |
梦想着成为一个资深的技术大牛,实现财富自由,生活越来越好
10 |
我有很多想做的事:蹦极、去黄山观云海、去钱塘江看潮...
11 |
乐观看待生活,努力改变人生!
12 |
13 |
14 |
15 | 成长就是你主观世界遇到客观世界之间的那条沟,你掉进去了,叫挫折,爬出来了,叫成长。
17 | ——罗振宇
19 |
20 |
24 |
25 |
42 |
43 |
44 |
45 |
53 |
195 |
--------------------------------------------------------------------------------
/MyBlogFront/src/views/List.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{ tipText }}
5 |
6 |
7 |
13 |
14 |
15 |
{{ item.title }}
16 |
17 | {{ item.type == "blog" ? "博客" : "心情" }}
18 |
19 |
20 |
文章简介:{{ item.digest }}
21 |
22 |
40 |
41 |
45 |
46 |
56 |
57 |
58 |
59 |
148 |
149 |
216 |
--------------------------------------------------------------------------------
/MyBlogFront/src/views/MessageBoard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
留言板
6 |
欢迎访问我的博客,我是孤城浪人,一名零零后程序猿。
7 |
8 |
9 | 当我站在二十岁的分岔口去回忆我的前二十年人生,却是一片模糊,似乎有过意难平,似乎弄丢了一些人,似乎...有很多很多有意思的事,可再也记不起来了,就好像这些经历属于带面具的我,不属于我,
10 | 留给我的只是一堆遗憾罢了。
11 |
12 |
13 |
14 | 现在,在这稍纵即逝的青春的尾巴上,我被生活裹挟着向前疾驰,希望能够留下些沿途的风景,于是有了在这个博客。
15 |
16 |
17 |
这些是我想说的话,你想对我说些什么呢?
18 |
19 |
20 |
21 |
23 |
24 |
25 |
26 |
27 |
48 |
49 |
61 |
--------------------------------------------------------------------------------
/MyBlogFront/src/views/PhotoWall.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
20 |
21 |
31 |
39 |
40 |
{{ cart.shootingTime }}
41 |
42 |
43 |
44 |
45 |
46 |
47 |
123 |
124 |
151 |
--------------------------------------------------------------------------------
/MyBlogFront/src/views/TimeClue.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
{{ timeNode.title }}
13 |
{{ timeNode.digest }}
14 |
15 |
16 |
17 |
18 |
19 |
49 |
74 |
--------------------------------------------------------------------------------
/MyBlogFront/vue.config.js:
--------------------------------------------------------------------------------
1 | const CompressionPlugin = require('compression-webpack-plugin'); //引入
2 | module.exports = {
3 | lintOnSave: false,
4 | transpileDependencies: true,
5 | devServer: {
6 | proxy: 'http://localhost:3000',
7 | },
8 | productionSourceMap: false,
9 | configureWebpack: {
10 | externals: {
11 | vue: 'Vue',
12 | // 'vue-router': 'VueRouter',
13 | // vuex: 'Vuex',
14 | axios: 'axios',
15 | 'element-ui': 'ELEMENT',
16 | },
17 | },
18 | configureWebpack: config => {
19 | // 公共代码抽离
20 | config.optimization = {
21 | splitChunks: {
22 | cacheGroups: {
23 | libs: {
24 | name: 'chunk-libs',
25 | test: /[\\/]node_modules[\\/]/,
26 | priority: 10,
27 | chunks: 'initial', // only package third parties that are initially dependent
28 | },
29 | common: {
30 | chunks: 'all',
31 | test: /[\\/]src[\\/]js[\\/]/,
32 | name: 'common',
33 | minChunks: 2,
34 | maxInitialRequests: 5,
35 | minSize: 0,
36 | priority: 60,
37 | },
38 | styles: {
39 | name: 'styles',
40 | test: /\.(sa|sc|c)ss$/,
41 | chunks: 'all',
42 | enforce: true,
43 | },
44 | pinyin: {
45 | // split pinyin libs
46 | name: 'chunk-pinyin',
47 | test: /[\\/]node_modules[\\/]_?pinyin(.*)/,
48 | priority: 40,
49 | chunks: 'async',
50 | reuseExistingChunk: true,
51 | },
52 | html2canvas: {
53 | // split html2canvas libs
54 | name: 'chunk-html2canvas',
55 | test: /[\\/]node_modules[\\/]_?html2canvas(.*)/,
56 | priority: 40,
57 | chunks: 'async',
58 | reuseExistingChunk: true,
59 | },
60 | 'vue-pdf': {
61 | // split vue-pdf libs
62 | name: 'chunk-vue-pdf',
63 | test: /[\\/]node_modules[\\/]_?vue-pdf(.*)/,
64 | priority: 40,
65 | chunks: 'async',
66 | reuseExistingChunk: true,
67 | },
68 | runtimeChunk: {
69 | name: 'manifest',
70 | },
71 | },
72 | },
73 | };
74 | },
75 | // configureWebpack: config => {
76 | // if (process.env.NODE_ENV === 'production') {
77 | // config.plugins.push(
78 | // new CompressionPlugin({
79 | // algorithm: 'gzip',
80 | // test: /\.js$|\.html$|\.css$|\.jpg$|\.png/,
81 | // threshold: 10240,
82 | // minRatio: 0.5,
83 | // deleteOriginalAssets: true, // 是否删除源文件
84 | // })
85 | // );
86 | // }
87 | // },
88 | };
89 |
--------------------------------------------------------------------------------
/MyBlogServe/app.js:
--------------------------------------------------------------------------------
1 | const createError = require('http-errors');
2 | const express = require('express');
3 | const path = require('path');
4 | const cookieParser = require('cookie-parser');
5 | const logger = require('morgan');
6 | const session = require('express-session');
7 | // 数据库
8 | const db = require('./db/connect');
9 |
10 | // 引入路由
11 | const usersRouter = require('./routes/users');
12 | const arrticlesRouter = require('./routes/blogs');
13 | const jottingsRouter = require('./routes/jottings');
14 | const classifiesRouter = require('./routes/classifies');
15 | const synthesisRouter = require('./routes/synthesis');
16 | const commentRouter = require('./routes/comments');
17 | const routeRouter = require('./routes/routes');
18 | const murmurRouter = require('./routes/murmur');
19 | const photoRouter = require('./routes/photo');
20 | const timeclueRouter = require('./routes/timeclue.js');
21 | const app = express();
22 |
23 | app.use(session({
24 | secret: '####',
25 | name: 'sessionId',
26 | resave: false,
27 | saveUninitialized: false,
28 | cookie: {
29 | maxAge: 1000 * 60 * 60
30 | }
31 | }));
32 | // view engine setup
33 | app.set('views', path.join(__dirname, 'views'));
34 | app.set('view engine', 'jade');
35 | app.use(logger('dev'));
36 | app.use(express.json());
37 | app.use(express.urlencoded({ extended: false }));
38 | app.use(cookieParser());
39 | app.use(express.static(path.join(__dirname, 'public')));
40 |
41 | // 注册路由
42 | app.use('/api/users', usersRouter);
43 | app.use('/api/blogs', arrticlesRouter);
44 | app.use('/api/jottings', jottingsRouter);
45 | app.use('/api/classifies', classifiesRouter);
46 | app.use('/api/synthesis', synthesisRouter);
47 | app.use('/api/comments', commentRouter);
48 | app.use('/api/timeclues', timeclueRouter);
49 | app.use('/api/routes', routeRouter);
50 | app.use('/api/murmur', murmurRouter);
51 | app.use('/api/photo', photoRouter);
52 | // catch 404 and forward to error handler
53 | app.use(function(req, res, next) {
54 | next(createError(404));
55 | });
56 |
57 | // error handler
58 | app.use(function(err, req, res, next) {
59 | // set locals, only providing error in development
60 | res.locals.message = err.message;
61 | res.locals.error = req.app.get('env') === 'development' ? err : {};
62 |
63 | // render the error page
64 | res.status(err.status || 500);
65 | res.render('error');
66 | });
67 |
68 | module.exports = app;
69 |
--------------------------------------------------------------------------------
/MyBlogServe/bin/www:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | /**
4 | * Module dependencies.
5 | */
6 |
7 | var app = require('../app');
8 | var debug = require('debug')('myblogserve:server');
9 | var http = require('http');
10 |
11 | /**
12 | * Get port from environment and store in Express.
13 | */
14 |
15 | var port = normalizePort(process.env.PORT || '3000');
16 | app.set('port', port);
17 |
18 | /**
19 | * Create HTTP server.
20 | */
21 |
22 | var server = http.createServer(app);
23 |
24 | /**
25 | * Listen on provided port, on all network interfaces.
26 | */
27 |
28 | server.listen(port);
29 | server.on('error', onError);
30 | server.on('listening', onListening);
31 |
32 | /**
33 | * Normalize a port into a number, string, or false.
34 | */
35 |
36 | function normalizePort(val) {
37 | var port = parseInt(val, 10);
38 |
39 | if (isNaN(port)) {
40 | // named pipe
41 | return val;
42 | }
43 |
44 | if (port >= 0) {
45 | // port number
46 | return port;
47 | }
48 |
49 | return false;
50 | }
51 |
52 | /**
53 | * Event listener for HTTP server "error" event.
54 | */
55 |
56 | function onError(error) {
57 | if (error.syscall !== 'listen') {
58 | throw error;
59 | }
60 |
61 | var bind = typeof port === 'string'
62 | ? 'Pipe ' + port
63 | : 'Port ' + port;
64 |
65 | // handle specific listen errors with friendly messages
66 | switch (error.code) {
67 | case 'EACCES':
68 | console.error(bind + ' requires elevated privileges');
69 | process.exit(1);
70 | break;
71 | case 'EADDRINUSE':
72 | console.error(bind + ' is already in use');
73 | process.exit(1);
74 | break;
75 | default:
76 | throw error;
77 | }
78 | }
79 |
80 | /**
81 | * Event listener for HTTP server "listening" event.
82 | */
83 |
84 | function onListening() {
85 | var addr = server.address();
86 | var bind = typeof addr === 'string'
87 | ? 'pipe ' + addr
88 | : 'port ' + addr.port;
89 | debug('Listening on ' + bind);
90 | }
91 |
--------------------------------------------------------------------------------
/MyBlogServe/controllers/blogs.js:
--------------------------------------------------------------------------------
1 | const BlogsModel = require('../model/blogs');
2 | const ClassifyModel = require('../model/classifies');
3 | const TagModel = require('../model/tag');
4 | const util = require('../utils');
5 | // 添加新博客
6 | const addBlog = async (req, res) => {
7 | const { title, classification, content, digest, state, tags } = req.body;
8 | console.log(classification);
9 | const blog = await BlogsModel.addblog({
10 | date: Date.now(),
11 | title,
12 | classification,
13 | content,
14 | digest,
15 | state,
16 | tags,
17 | });
18 | await ClassifyModel.updateClassifySum(classification, 1);
19 | if (blog) {
20 | res.send({
21 | msg: '博客添加成功',
22 | status: 200,
23 | });
24 | } else {
25 | res.send({
26 | msg: '博客添加失败!',
27 | status: 0,
28 | });
29 | }
30 | };
31 | // 修改博客状态
32 | const changeBlogState = async (req, res) => {
33 | const { _id } = req.query;
34 | const blog = await BlogsModel.getBlog(_id);
35 | const result = await BlogsModel.changeBlogState(!blog.state, _id);
36 | if (result.acknowledged && result.modifiedCount != 0) {
37 | res.send({
38 | msg: '博客状态修改成功',
39 | status: 200,
40 | });
41 | } else {
42 | res.send({
43 | msg: '博客状态修改失败!',
44 | status: 0,
45 | });
46 | }
47 | };
48 | // 更新博客
49 | const updateBlog = async (req, res) => {
50 | const { content, _id, digest, title, tags } = req.body;
51 | const result = await BlogsModel.updateBlog(_id, content, digest, title, tags);
52 | if (result.acknowledged && result.modifiedCount !== 0) {
53 | res.send({
54 | msg: '博客已更新',
55 | status: 200,
56 | });
57 | } else {
58 | res.send({
59 | msg: '更新失败!',
60 | status: 0,
61 | });
62 | }
63 | };
64 | // 获取文章列表
65 | const getBlogs = async (req, res) => {
66 | const blogs = await BlogsModel.getBlogs();
67 | blogs.forEach(item => (item.date = util.formatDate(item.date)));
68 | if (blogs) {
69 | res.send({
70 | msg: '博客查询成功',
71 | status: 200,
72 | data: blogs,
73 | });
74 | } else {
75 | res.send({
76 | msg: '博客查询失败',
77 | status: 200,
78 | });
79 | }
80 | };
81 | // 获取已发布文章列表
82 | const getPublishBlogs = async (req, res) => {
83 | const { pageStart, pageSize } = req.query;
84 | const dataList = await BlogsModel.getPublishBlogs(pageStart, pageSize);
85 | const count = await BlogsModel.getblogSums();
86 | dataList.forEach(item => (item.date = util.formatDate(item.date)));
87 | if (dataList) {
88 | res.send({
89 | msg: '博客查询成功',
90 | status: 200,
91 | data: { dataList, count },
92 | });
93 | } else {
94 | res.send({
95 | msg: '博客查找失败',
96 | status: 0,
97 | });
98 | }
99 | };
100 | // 删除文章
101 | const deleteBlog = async (req, res) => {
102 | const { _id, classification } = req.query;
103 | const deleteBlog = await BlogsModel.deleteBlog(_id);
104 | ClassifyModel.updateClassifySum(classification, -1);
105 | if (deleteBlog.acknowledged && deleteBlog.deletedCount !== 0) {
106 | res.send({
107 | msg: '博客删除成功',
108 | status: 200,
109 | });
110 | } else {
111 | res.send({
112 | msg: '博客删除失败!',
113 | status: 0,
114 | });
115 | }
116 | };
117 | // 获取某一个文章
118 | const getBlog = async (req, res) => {
119 | const { _id } = req.query;
120 | // 这里必须要await
121 | const blog = await BlogsModel.getBlog(_id);
122 | const tags = await TagModel.getTags();
123 | blog.tags = util.manageTags(blog.tags, tags);
124 | blog.date = util.formatDate(blog.date);
125 | const classify = await ClassifyModel.getClassify(blog.classification);
126 | blog.classifyName = classify?.title;
127 | // 查询博客所属书签
128 | if (blog) {
129 | res.send({
130 | msg: '博客查找成功',
131 | status: 200,
132 | data: blog,
133 | });
134 | } else {
135 | res.send({
136 | msg: '博主正在马不停蹄的创作中,敬请谅解!',
137 | status: 0,
138 | });
139 | }
140 | };
141 | // 获取某专栏下所有博客
142 | const getBlogsOfClassify = async (req, res) => {
143 | const { classification } = req.query;
144 | const dataList = await BlogsModel.getBlogsOfClassify(classification);
145 | dataList.forEach(item => (item.date = util.formatDate(item.date)));
146 | if (dataList) {
147 | res.send({
148 | msg: '查找博客成功',
149 | status: 200,
150 | data: {
151 | dataList,
152 | },
153 | });
154 | } else {
155 | res.send({
156 | msg: '博主正在加班加点的创作中,敬请谅解!',
157 | status: 0,
158 | });
159 | }
160 | };
161 | // 点赞
162 | const addFavour = async (req, res) => {
163 | const { _id, favourMurmur } = req.query;
164 | // 增加点赞数
165 | const addFavour = await BlogsModel.addFavour(_id, favourMurmur);
166 | const getFavour = await BlogsModel.getFavour(_id);
167 | if (addFavour) {
168 | res.send({
169 | msg: '博客点赞成功',
170 | status: 200,
171 | data: getFavour.favour,
172 | });
173 | } else {
174 | res.send({
175 | msg: '博客点赞失败!',
176 | status: 0,
177 | });
178 | }
179 | };
180 | // 增加浏览量
181 | const addBlogBrowse = async (req, res) => {
182 | const { _id } = req.query;
183 | const result = await BlogsModel.addBlogBrowse(_id);
184 | if (result.modifiedCount === 1) {
185 | res.send({
186 | msg: '博客浏览量增加成功',
187 | status: 200,
188 | });
189 | } else {
190 | res.send({
191 | msg: '博客浏览量增加失败',
192 | status: 0,
193 | });
194 | }
195 | };
196 | module.exports = {
197 | addBlog,
198 | changeBlogState,
199 | updateBlog,
200 | getBlogs,
201 | getPublishBlogs,
202 | deleteBlog,
203 | getBlog,
204 | getBlogsOfClassify,
205 | addFavour,
206 | addBlogBrowse,
207 | };
208 |
--------------------------------------------------------------------------------
/MyBlogServe/controllers/classifies.js:
--------------------------------------------------------------------------------
1 | const ClassifyModel = require('../model/classifies');
2 | const util = require('../utils');
3 | // 添加新专栏
4 | const addClassify = async (req, res) => {
5 | const { title, digest } = req.body;
6 | const result = await ClassifyModel.addClassify({
7 | date: Date.now(),
8 | title,
9 | digest,
10 | bgColor: util.randomColor(),
11 | });
12 | if (result) {
13 | res.send({
14 | msg: '专栏添加成功',
15 | status: 200,
16 | });
17 | } else {
18 | res.send({
19 | msg: '专栏添加失败!',
20 | status: 0,
21 | });
22 | }
23 | };
24 | // 获取所有专栏
25 | const getClassifies = async (req, res) => {
26 | const classifies = await ClassifyModel.getClassifies();
27 | classifies.forEach(item => item.date = util.formatDate(item.date));
28 | if (classifies) {
29 | res.send({
30 | msg: '专栏查询成功',
31 | status: 200,
32 | data: classifies,
33 | });
34 | } else {
35 | res.send({
36 | msg: '专栏查询失败',
37 | status: 0,
38 | });
39 | }
40 | };
41 | // 修改专栏描述标题
42 | const updateClassifyTitle = async (req, res) => {
43 | const { _id, title, digest } = req.body;
44 | const result = await ClassifyModel.updateClassifyTitle(_id, title, digest);
45 | if (result.acknowledged && result.modifiedCount !== 0) {
46 | res.send({
47 | msg: '专栏编辑成功',
48 | status: 200,
49 | data: result,
50 | });
51 | } else {
52 | res.send({
53 | msg: '专栏编辑失败',
54 | status: 0,
55 | });
56 | }
57 | };
58 | // 删除专栏
59 | const deleteClassify = async (req, res) => {
60 | const { _id } = req.query;
61 | // 这里必须要await
62 | const article = await ClassifyModel.getClassify(_id);
63 | const { articleNum } = article;
64 | if (articleNum != 0) {
65 | res.send({
66 | msg: '专栏博客不为零,无法删除专栏',
67 | status: 0,
68 | });
69 | } else {
70 | const result = await ClassifyModel.deleteClassify(_id);
71 | if (result.acknowledged && result.deletedCount !== 0) {
72 | res.send({
73 | msg: '专栏删除成功',
74 | status: 200,
75 | });
76 | } else {
77 | res.send({
78 | msg: '专栏删除失败!',
79 | status: 0,
80 | });
81 | }
82 | }
83 | };
84 |
85 | module.exports = {
86 | updateClassifyTitle,
87 | deleteClassify,
88 | addClassify,
89 | getClassifies,
90 | };
91 |
--------------------------------------------------------------------------------
/MyBlogServe/controllers/comments.js:
--------------------------------------------------------------------------------
1 | const CommentModel = require('../model/comments');
2 | const MurmruModel = require('../model/murmurs');
3 | const util = require('../utils');
4 | // 添加新一级评论
5 | const addFirstComment = async (req, res, next) => {
6 | // 获取时间字符串
7 | const { keyId, articleTitle, content, murmur, replyInfo = [] } = req.body;
8 | const result = await CommentModel.addFirstComment({
9 | date: Date.now(),
10 | keyId,
11 | // username,
12 | content,
13 | murmur,
14 | replyInfo,
15 | articleTitle,
16 | });
17 | const comment = result.toObject();
18 | comment.date = util.formatTime(comment.date);
19 | if (comment) {
20 | res.send({
21 | msg: '评论成功',
22 | status: 200,
23 | data: comment,
24 | });
25 | } else {
26 | res.send({
27 | msg: '评论失败!',
28 | status: 0,
29 | });
30 | }
31 | };
32 | // 添加新次级评论
33 | const addSecondComment = async (req, res, next) => {
34 | // 获取时间字符串
35 | const { _id, date, reply, murmur, replyName, replyId } = req.body;
36 | const result = await CommentModel.addSecondComment(_id, {
37 | date: Date.now(),
38 | // replymurmur,
39 | replyId,
40 | // username,
41 | reply,
42 | murmur,
43 | replyName,
44 | });
45 | if (result.acknowledged && result.modifiedCount !== 0) {
46 | const comment = await CommentModel.getCommentReplyLast(_id);
47 | const newCom = comment.replyInfo.pop().toObject();
48 | newCom.date = util.formatTime(newCom.date);
49 | res.send({
50 | msg: '评论成功',
51 | status: 200,
52 | data: newCom,
53 | });
54 | } else {
55 | res.send({
56 | msg: '评论失败!',
57 | status: 0,
58 | });
59 | }
60 | };
61 | // 给一级评论点赞
62 | const addFirstFavour = async (req, res) => {
63 | const { _id, favourMurmur } = req.query;
64 | const result = await CommentModel.addFirstFavour(_id, favourMurmur);
65 | if (result.acknowledged && result.modifiedCount !== 0) {
66 | res.send({
67 | msg: '点赞成功',
68 | status: 200,
69 | });
70 | } else {
71 | res.send({
72 | msg: '点赞失败',
73 | status: 0,
74 | });
75 | }
76 | };
77 | // 给次级评论点赞
78 | const addSecondFavour = async (req, res) => {
79 | const { _id, replyId, favourMurmur } = req.query;
80 | const result = await CommentModel.addSecondFavour(_id, replyId, favourMurmur);
81 | if (result.acknowledged && result.modifiedCount !== 0) {
82 | res.send({
83 | msg: '点赞成功',
84 | status: 200,
85 | });
86 | } else {
87 | res.send({
88 | msg: '点赞失败',
89 | status: 0,
90 | });
91 | }
92 | };
93 | // 删除一级评论
94 | const deleteFirstComment = async (req, res, next) => {
95 | const { _id } = req.query;
96 | const result = await CommentModel.deleteFirstComment(_id);
97 | if (result.acknowledged && result.deletedCount !== 0) {
98 | res.send({
99 | msg: '删除成功',
100 | status: 200,
101 | data: result,
102 | });
103 | } else {
104 | res.send({
105 | msg: '删除失败',
106 | status: 0,
107 | });
108 | }
109 | };
110 | // 删除次级评论
111 | const deleteSecondComment = async (req, res, next) => {
112 | const { _id, replyId } = req.query;
113 | const result = await CommentModel.deleteSecondComment(_id, replyId);
114 | if (result.acknowledged && result.modifiedCount !== 0) {
115 | res.send({
116 | msg: '删除成功',
117 | status: 200,
118 | });
119 | } else {
120 | res.send({
121 | msg: '删除失败',
122 | status: 0,
123 | });
124 | }
125 | };
126 | // 查询某一篇文章的所有评论
127 | const getCommentsOfArticle = async (req, res) => {
128 | const { id, pageSize, pageStart, murmur } = req.query;
129 | // 这里必须要await
130 | let comments = await CommentModel.getCommentsOfArticle(id, pageSize, pageStart);
131 | const murmurInfos = await MurmruModel.getMurmurInfos();
132 | const user = await MurmruModel.getMurmurInfo(murmur);
133 | comments = util.manageMurmurComments(murmurInfos, comments);
134 | if (comments) {
135 | res.send({
136 | msg: '查询成功',
137 | status: 200,
138 | data: { comments, user },
139 | });
140 | } else {
141 | res.send({
142 | msg: '查询失败',
143 | status: 0,
144 | });
145 | }
146 | };
147 | // 查询所有的评论
148 | const getComments = async (req, res) => {
149 | // const { pageSize, pageStart, murmur } = req.query;
150 | // 这里必须要await
151 | let comments = await CommentModel.getComments();
152 | const murmurInfos = await MurmruModel.getMurmurInfos();
153 | comments = util.manageMurmurComments(murmurInfos, comments);
154 | if (comments) {
155 | res.send({
156 | msg: '查询成功',
157 | status: 200,
158 | data: comments,
159 | });
160 | } else {
161 | res.send({
162 | msg: '查询失败',
163 | status: 0,
164 | });
165 | }
166 | };
167 | module.exports = {
168 | addFirstComment,
169 | addSecondComment,
170 | addFirstFavour,
171 | addSecondFavour,
172 | deleteFirstComment,
173 | deleteSecondComment,
174 | getCommentsOfArticle,
175 | getComments,
176 | };
177 |
--------------------------------------------------------------------------------
/MyBlogServe/controllers/jottings.js:
--------------------------------------------------------------------------------
1 | const JottingModel = require('../model/jottings');
2 | const TagModel = require('../model/tag');
3 | const util = require('../utils');
4 | const addJotting = async (req, res, next) => {
5 | let { title, content, digest, state, tags } = req.body;
6 | let result = await JottingModel.addJotting({
7 | date: Date.now(),
8 | title,
9 | content,
10 | digest,
11 | state,
12 | tags,
13 | });
14 | if (result) {
15 | res.send({
16 | msg: '随笔添加成功',
17 | status: 200,
18 | });
19 | } else {
20 | res.send({
21 | msg: '随笔添加失败',
22 | status: 0,
23 | });
24 | }
25 | };
26 | // 修改随笔的状态
27 | const changeState = async (req, res) => {
28 | let { _id } = req.query;
29 | let jotting = await JottingModel.getJotting(_id);
30 | let result = await JottingModel.changeJottingState(!jotting.state, _id);
31 | if (result.acknowledged && result.modifiedCount !== 0) {
32 | res.send({
33 | msg: '随笔状态修改成功',
34 | status: 200,
35 | });
36 | } else {
37 | res.send({
38 | msg: '随笔状态修改失败',
39 | status: 0,
40 | });
41 | }
42 | };
43 | // 修改随笔内容
44 | const updateJotting = async (req, res, next) => {
45 | let { content, _id, title, digest, tags } = req.body;
46 | let result = await JottingModel.updateJotting(_id, { content, digest, title, tags });
47 | if (result.acknowledged && result.modifiedCount !== 0) {
48 | res.send({
49 | msg: '随笔修改成功',
50 | status: 200,
51 | });
52 | } else {
53 | res.send({
54 | msg: '随笔修改失败',
55 | status: 0,
56 | });
57 | }
58 | };
59 | // 获取随笔列表
60 | const getJottings = async (req, res, next) => {
61 | let result = await JottingModel.getJottings();
62 | result.forEach(item => {
63 | item.date = util.formatDate(item.date);
64 | });
65 | if (result) {
66 | res.send({
67 | msg: '随笔查询成功',
68 | status: 200,
69 | data: result,
70 | });
71 | } else {
72 | res.send({
73 | msg: '博主正在加班加点的创作中,敬请谅解!',
74 | status: 0,
75 | });
76 | }
77 | };
78 | // 获取已发布文章列表
79 | const getPublishJottings = async (req, res, next) => {
80 | let { pageStart, pageSize } = req.query;
81 | let dataList = await JottingModel.getPublishJottings(pageStart, pageSize);
82 | dataList.forEach(item => {
83 | item.date = util.formatDate(item.date);
84 | });
85 |
86 | let count = await JottingModel.getJottingSums();
87 | if (dataList) {
88 | res.send({
89 | msg: '随笔查询成功',
90 | status: 200,
91 | data: { dataList, count },
92 | });
93 | } else {
94 | res.send({
95 | msg: '博主正在加班加点的创作中,敬请谅解!',
96 | status: 0,
97 | });
98 | }
99 | };
100 | // 获取某一随笔
101 | const getJotting = async (req, res, next) => {
102 | let { _id } = req.query;
103 | let jotting = await JottingModel.getJotting(_id);
104 | const tags = await TagModel.getTags();
105 | jotting.tags = util.manageTags(jotting.tags, tags);
106 | jotting.date = util.formatDate(jotting.date);
107 | if (jotting) {
108 | res.send({
109 | msg: '随笔详情查询成功',
110 | status: 200,
111 | data: jotting,
112 | });
113 | } else {
114 | res.send({
115 | msg: '随笔详情查询失败',
116 | status: 0,
117 | });
118 | }
119 | };
120 | // 点赞某一随笔
121 | const addBrowse = async (req, res, next) => {
122 | let { _id } = req.query;
123 | let jotting = await JottingModel.addBrowse(_id);
124 | if (result.acknowledged && jotting.modifiedCount !== 0) {
125 | res.send({
126 | msg: '随笔点赞成功',
127 | status: 200,
128 | data: jotting,
129 | });
130 | } else {
131 | res.send({
132 | msg: '随笔点赞失败',
133 | status: 0,
134 | });
135 | }
136 | };
137 | // 删除随笔
138 | const deleteJotting = async (req, res, next) => {
139 | const { _id } = req.query;
140 | let result = await JottingModel.deleteJotting(_id);
141 | if (result.acknowledged && result.deletedCount !== 0) {
142 | res.send({
143 | msg: '随笔删除成功',
144 | status: 200,
145 | });
146 | } else {
147 | res.send({
148 | msg: '随笔删除失败',
149 | status: 0,
150 | });
151 | }
152 | };
153 | // 点赞
154 | const addFavour = async (req, res) => {
155 | let { _id, favourMurmur } = req.query;
156 | let addFavour = await JottingModel.addFavour(_id, favourMurmur);
157 | let getFavour = await JottingModel.getFavour(_id);
158 | if (addFavour.acknowledged && addFavour.modifiedCount !== 0) {
159 | res.send({
160 | msg: '点赞随笔成功',
161 | status: 200,
162 | data: getFavour.favour,
163 | });
164 | } else {
165 | res.send({
166 | msg: '点赞随笔失败',
167 | status: 0,
168 | });
169 | }
170 | };
171 |
172 | // 增加浏览量
173 | const addJottingBrowse = async (req, res) => {
174 | let { _id } = req.query;
175 | let addBrowse = await JottingModel.addJottingBrowse(_id);
176 | if (addBrowse.acknowledged && addBrowse.modifiedCount !== 0) {
177 | res.send({
178 | msg: '随笔浏览量增加成功',
179 | status: 200,
180 | });
181 | } else {
182 | res.send({
183 | msg: '随笔浏览量增加失败',
184 | status: 0,
185 | });
186 | }
187 | };
188 | module.exports = {
189 | getJottings,
190 | deleteJotting,
191 | updateJotting,
192 | addJotting,
193 | changeState,
194 | getPublishJottings,
195 | getJotting,
196 | addFavour,
197 | addBrowse,
198 | addJottingBrowse,
199 | };
200 |
--------------------------------------------------------------------------------
/MyBlogServe/controllers/murmur.js:
--------------------------------------------------------------------------------
1 | const MurmruModel = require('../model/murmurs');
2 | const util = require('../utils');
3 | // 新增指纹信息
4 | const addMurmurInfo = async (req, res) => {
5 | const { murmur, username, avatarUrl } = req.body;
6 | const result = await MurmruModel.addMurmur({ date: Date.now(), murmur, username, avatarUrl });
7 | if (result) {
8 | res.send({
9 | msg: '新增浏览器指纹信息成功',
10 | status: 200,
11 | data: result,
12 | });
13 | } else {
14 | res.send({
15 | msg: '新增浏览器指纹信息失败',
16 | status: 0,
17 | });
18 | }
19 | };
20 | // 更新用户名
21 | const updateMurmurUsername = async (req, res, next) => {
22 | const { murmur, username } = req.body;
23 | let result = await MurmruModel.updateMurmurUsername(murmur, username);
24 | if (result.acknowledged && result.modifiedCount != 0) {
25 | res.send({
26 | msg: '更新用户名成功',
27 | status: 200,
28 | });
29 | } else {
30 | res.send({
31 | msg: '更新用户名失败',
32 | status: 0,
33 | });
34 | }
35 | };
36 | //查询所有用户信息
37 | const getMurmurInfos = async (req, res, next) => {
38 | let result = await MurmruModel.getMurmurInfos();
39 | result.forEach(item => (item.date = util.formatDate(item.date)));
40 | if (result) {
41 | res.send({
42 | msg: '查询成功',
43 | status: 200,
44 | data: result,
45 | });
46 | } else {
47 | res.send({
48 | msg: '查询失败',
49 | status: 0,
50 | });
51 | }
52 | };
53 | //查询所有用户信息
54 | const deleteMurmurInfo = async (req, res, next) => {
55 | const { id } = req.query;
56 | const result = await MurmruModel.deleteMurmurInfo(id);
57 | if (result.acknowledged && result.deletedCount != 0) {
58 | res.send({
59 | msg: '删除成功',
60 | status: 200,
61 | });
62 | } else {
63 | res.send({
64 | msg: '删除失败',
65 | status: 0,
66 | });
67 | }
68 | };
69 | module.exports = {
70 | addMurmurInfo,
71 | updateMurmurUsername,
72 | getMurmurInfos,
73 | deleteMurmurInfo,
74 | };
75 |
--------------------------------------------------------------------------------
/MyBlogServe/controllers/photo.js:
--------------------------------------------------------------------------------
1 | const PhotoModel = require('../model/photo');
2 | const util = require('../utils');
3 | const path = require('path');
4 | const fs = require('fs');
5 | // 添加新图片
6 | const addPhoto = async (req, res) => {
7 | const { digest, shootingTime } = req.body;
8 | const file = req.file;
9 | const photoUrl = util.imgBaseUrl('photo') + file.filename;
10 | const url = path.join(__dirname, '../public/photos/', file.filename);
11 |
12 | const result = await PhotoModel.addPhoto({
13 | uploadTime: Date.now(),
14 | shootingTime,
15 | photoUrl,
16 | digest,
17 | thumbnailUrl: '',
18 | preBg: util.randomColor(),
19 | });
20 | console.log(fs.existsSync(url), result);
21 | if (result && fs.existsSync(url)) {
22 | res.send({
23 | msg: '照片添加成功',
24 | status: 200,
25 | });
26 | } else {
27 | res.send({
28 | msg: '照片添加失败!',
29 | status: 0,
30 | });
31 | }
32 | };
33 | // 获取照片
34 | const getPhotos = async (req, res) => {
35 | const photos = await PhotoModel.getPhotos();
36 | photos.forEach(item => {
37 | item.uploadTime = util.formatDate(item.uploadTime);
38 | item.shootingTime = util.formatDate(item.shootingTime);
39 | });
40 | if (photos) {
41 | res.send({
42 | msg: '查询成功',
43 | status: 200,
44 | data: photos,
45 | });
46 | } else {
47 | res.send({
48 | msg: '查询失败',
49 | status: 0,
50 | });
51 | }
52 | };
53 | // 修改照片信息
54 | const updatePhotoDigest = async (req, res) => {
55 | const { _id, digest, shootingTime } = req.body;
56 | const result = await PhotoModel.updatePhoto(_id, digest, shootingTime);
57 | if (result.acknowledged && result.modifiedCount !== 0) {
58 | res.send({
59 | msg: '照片信息编辑成功',
60 | status: 200,
61 | data: result,
62 | });
63 | } else {
64 | res.send({
65 | msg: '照片信息编辑失败',
66 | status: 0,
67 | });
68 | }
69 | };
70 | // 删除照片
71 | const deletePhoto = async (req, res) => {
72 | const { _id } = req.query;
73 | const result = await PhotoModel.deletePhoto(_id);
74 | if (result.acknowledged && result.deletedCount !== 0) {
75 | res.send({
76 | msg: '照片删除成功',
77 | status: 200,
78 | });
79 | } else {
80 | res.send({
81 | msg: '照片删除失败!',
82 | status: 0,
83 | });
84 | }
85 | };
86 |
87 | module.exports = {
88 | updatePhotoDigest,
89 | deletePhoto,
90 | addPhoto,
91 | getPhotos,
92 | };
93 |
--------------------------------------------------------------------------------
/MyBlogServe/controllers/routes.js:
--------------------------------------------------------------------------------
1 | const RouteModel = require('../model/routes');
2 | const { sign, verify, hash, compare, date } = require('../utils');
3 | // 添加新路由
4 | const addFirstRoute = async (req, res) => {
5 | const { route } = req.body;
6 | const result = await RouteModel.addFirstRoute(route);
7 | if (result) {
8 | res.send({
9 | msg: '添加成功',
10 | status: 200,
11 | });
12 | } else {
13 | res.send({
14 | msg: '添加失败!',
15 | status: 0,
16 | });
17 | }
18 | };
19 | const addSecondRoute = async (req, res, next) => {
20 | const { route, parentRouteName } = req.body;
21 | const router = await RouteModel.getRouteByPath(route.path);
22 | if (router) {
23 | res.send({
24 | msg: '路径重复!',
25 | status: 0,
26 | });
27 | } else {
28 | const result = await RouteModel.addSecondRoute(parentRouteName, route);
29 | if (result.acknowledged && result.modifiedCount !== 0) {
30 | res.send({
31 | msg: '添加成功',
32 | status: 200,
33 | });
34 | } else {
35 | res.send({
36 | msg: '添加失败!',
37 | status: 0,
38 | });
39 | }
40 | }
41 | };
42 | // 修改路由
43 | const updatRoute = async (req, res, next) => {
44 | const { route } = req.body;
45 | const result = await RouteModel.updateFirstRouteInfo(route);
46 | if (result.acknowledged && result.modifiedCount != 0) {
47 | res.send({
48 | msg: '修改成功',
49 | status: 200,
50 | });
51 | } else {
52 | res.send({
53 | msg: '修改失败',
54 | status: 0,
55 | });
56 | }
57 | };
58 | // 获取路由列表
59 | const getRoutes = async (req, res, next) => {
60 | const { role } = req.query;
61 | const result = await RouteModel.getRoutes();
62 | // console.log('rew', result);
63 |
64 | const route = _filterRoute(role, result);
65 | if (result) {
66 | res.send({
67 | msg: '查询成功',
68 | status: 200,
69 | data: route,
70 | });
71 | } else {
72 | res.send({
73 | msg: '查询失败',
74 | status: -1,
75 | });
76 | }
77 | };
78 | // 获取所有路由列表
79 | const getRouteList = async (req, res, next) => {
80 | const result = await RouteModel.getRoutes();
81 | if (result) {
82 | res.send({
83 | msg: '查询所有路由成功',
84 | status: 200,
85 | data: result,
86 | });
87 | } else {
88 | res.send({
89 | msg: '查询失败',
90 | status: 0,
91 | });
92 | }
93 | };
94 | // 递归处理符合条件的路由
95 | const _filterRoute = (role, routeList) => {
96 | const route = [];
97 | // console.log('r', routeList);
98 | routeList.forEach(item => {
99 | if (item.limits && item.limits.includes(role)) {
100 | const obj = {};
101 | obj._id = item._id;
102 | obj.path = item.path;
103 | obj.name = item.name;
104 | obj.component = item.component;
105 | obj.limits = item.limits;
106 | if (item.meta) {
107 | obj.meta = item.meta;
108 | }
109 | if (item.children && item.children.length !== 0) {
110 | obj.children = _filterRoute(role, item.children);
111 | }
112 | route.push(obj);
113 | }
114 | });
115 | return route;
116 | };
117 | // 删除路由
118 | const deleteRoute = async (req, res) => {
119 | const { _id } = req.query;
120 | const result = await RouteModel.deleteFirstRoute(_id);
121 | // if (!name) {
122 | // } else {
123 | // result = await RouteModel.deleteSecondRoute(_id, name);
124 | // }
125 | if (result.acknowledged && result.deletedCount != 0) {
126 | res.send({
127 | msg: '路由删除成功!',
128 | status: 200,
129 | });
130 | } else {
131 | res.send({
132 | msg: '路由删除失败!',
133 | status: -1,
134 | });
135 | }
136 | };
137 |
138 | module.exports = {
139 | addSecondRoute,
140 | addFirstRoute,
141 | updatRoute,
142 | getRoutes,
143 | deleteRoute,
144 | getRouteList,
145 | };
146 |
--------------------------------------------------------------------------------
/MyBlogServe/controllers/timeclue.js:
--------------------------------------------------------------------------------
1 | const TimeclueModel = require('../model/timeclue');
2 | const util = require('../utils');
3 | const addTimeclue = async (req, res) => {
4 | const { title, digest, date } = req.body;
5 | const timeclue = await TimeclueModel.addTimeclue({ title, date, digest });
6 | if (timeclue) {
7 | res.send({
8 | msg: '新增时间线信息成功',
9 | status: 200,
10 | data: timeclue,
11 | });
12 | } else {
13 | res.send({
14 | msg: '新增时间线信息失败',
15 | status: 0,
16 | });
17 | }
18 | };
19 | const updateTimeclue = async (req, res) => {
20 | const { _id, date, title, digest } = req.body;
21 | const timeclue = await TimeclueModel.uptateTimeclue(_id, date, title, digest);
22 | if (timeclue.acknowledged && timeclue.modifiedCount != 0) {
23 | res.send({
24 | msg: '时间线信息修改成功',
25 | status: 200,
26 | });
27 | } else {
28 | res.send({
29 | msg: '时间线信息修改失败',
30 | status: 0,
31 | });
32 | }
33 | };
34 | const changeTimeNodeState = async (req, res) => {
35 | const { id } = req.query;
36 | const { state } = await TimeclueModel.getTimeclue(id);
37 | const timeclue = await TimeclueModel.changeTimeNodeState(id, !state);
38 | if (timeclue.acknowledged && timeclue.modifiedCount != 0) {
39 | res.send({
40 | msg: '状态修改成功',
41 | status: 200,
42 | });
43 | } else {
44 | res.send({
45 | msg: '状态修改失败',
46 | status: 0,
47 | });
48 | }
49 | };
50 | //删除时间线信息
51 | const deleteTimeclue = async (req, res) => {
52 | const { _id } = req.query;
53 | const timeclue = await TimeclueModel.deleteTimeclue(_id);
54 | if (timeclue.acknowledged && timeclue.deletedCount != 0) {
55 | res.send({
56 | msg: '删除时间线信息成功',
57 | status: 200,
58 | });
59 | } else {
60 | res.send({
61 | msg: '删除时间线信息失败',
62 | status: 0,
63 | });
64 | }
65 | };
66 |
67 | //查找某一个时间线信息
68 | const getTimeclue = async (req, res) => {
69 | const { _id } = req.query;
70 | const timeclue = await TimeclueModel.getTimeclue(_id);
71 | if (timeclue) {
72 | res.send({
73 | msg: '查询时间线信息成功',
74 | status: 200,
75 | data: timeclue,
76 | });
77 | } else {
78 | res.send({
79 | msg: '查询时间线信息成功',
80 | status: 0,
81 | });
82 | }
83 | };
84 |
85 | //获取所有时间线信息
86 | const getTimeclues = async (req, res) => {
87 | const timeclues = await TimeclueModel.getTimeclues();
88 | timeclues.forEach(item => (item.date = util.formatDate(item.date)));
89 | if (timeclues) {
90 | res.send({
91 | msg: '获取时间线信息列表成功',
92 | status: 200,
93 | data: timeclues,
94 | });
95 | } else {
96 | res.send({
97 | msg: '获取时间线信息列表失败',
98 | status: 0,
99 | });
100 | }
101 | };
102 | module.exports = {
103 | addTimeclue,
104 | deleteTimeclue,
105 | getTimeclue,
106 | getTimeclues,
107 | updateTimeclue,
108 | changeTimeNodeState,
109 | };
110 |
--------------------------------------------------------------------------------
/MyBlogServe/controllers/users.js:
--------------------------------------------------------------------------------
1 | const UserModel = require('../model/users');
2 | const { sign, verify, hash, compare, formatDate } = require('../utils');
3 | // 添加新用户
4 | const register = async (req, res, next) => {
5 | let { username, password, email, role } = req.body;
6 | // 密码加密
7 | const bcryptPassword = await hash(password);
8 | // 检查此邮箱是否已经被注册
9 | const Email = await UserModel.getUser(email);
10 | if (!Email) {
11 | let result = await UserModel.addUser({
12 | username,
13 | password: bcryptPassword,
14 | email,
15 | date: Date.now(),
16 | role,
17 | });
18 |
19 | if (result) {
20 | res.send({
21 | msg: '注册成功',
22 | status: 200,
23 | });
24 | } else {
25 | res.send({
26 | msg: '注册失败了!请检查信息',
27 | status: 0,
28 | });
29 | }
30 | } else {
31 | res.send({
32 | msg: '此邮箱已经被注册,换个邮箱吧!',
33 | status: 0,
34 | });
35 | }
36 | };
37 | // 登录
38 | const login = async (req, res, next) => {
39 | let { email, password } = req.body;
40 | // 查找用户是否存在
41 | let user = await UserModel.getUser(email);
42 | if (user) {
43 | let { password: hash } = user;
44 | // 比较密码
45 | let compareResult = await compare(password, hash);
46 | if (compareResult) {
47 | let userInfo = {
48 | username: user.username,
49 | limits: user.limits,
50 | role: user.role,
51 | avatarUrl:user.avatarUrl
52 | };
53 | const token = sign(email);
54 | res.send({
55 | msg: '登陆成功',
56 | status: 200,
57 | data: {
58 | token: token,
59 | user: userInfo,
60 | },
61 | });
62 | } else {
63 | res.send({
64 | msg: '密码错误!',
65 | status: 0,
66 | });
67 | }
68 | } else {
69 | res.send({
70 | msg: '账号信息不存在!',
71 | status: 0,
72 | });
73 | }
74 | };
75 | // 登出
76 | const logout = async (req, res, next) => {
77 | req.session = null;
78 | res.send({
79 | msg: '退出成功',
80 | status: 200,
81 | });
82 | };
83 | // 进入登录态
84 | const getUserState = async (req, res, next) => {
85 | try {
86 | // 验证token
87 | let result = verify(token);
88 | res.send({
89 | msg: '已登录',
90 | status: 200,
91 | data: {
92 | username: result.username,
93 | },
94 | });
95 | } catch (err) {
96 | res.send({
97 | msg: '请登录',
98 | status: 0,
99 | });
100 | }
101 | };
102 | // 修改用户信息
103 | const updateUserInfo = async (req, res, next) => {
104 | let { email, role, username } = req.body;
105 | let result = await UserModel.updateUserInfo(email, role, username);
106 | if (result.acknowledged && result.modifiedCount !== 0) {
107 | res.send({
108 | msg: '用户信息修改成功',
109 | status: 200,
110 | });
111 | } else {
112 | res.send({
113 | msg: '用户信息修改失败',
114 | status: 0,
115 | });
116 | }
117 | };
118 |
119 | // 修改密码
120 | const updatePassword = async (req, res, next) => {
121 | let { email, password } = req.body;
122 | const bcryptPassword = await hash(password);
123 | let result = await UserModel.updatePassword(email, bcryptPassword);
124 | if (result.acknowledged && result.modifiedCount !== 0) {
125 | res.send({
126 | msg: '密码修改成功',
127 | status: 200,
128 | });
129 | } else {
130 | res.send({
131 | msg: '密码修改失败',
132 | status: 0,
133 | });
134 | }
135 | };
136 | // 获取用户列表
137 | const getUsers = async (req, res, next) => {
138 | const users = await UserModel.getUsers();
139 | users.forEach(item => (item.date = formatDate(item.date)));
140 | if (users) {
141 | res.send({
142 | msg: '查询用户成功',
143 | status: 200,
144 | data: users,
145 | });
146 | } else {
147 | res.send({
148 | msg: '查询用户失败',
149 | status: 0,
150 | });
151 | }
152 | };
153 | // 删除用户
154 | const deleteUser = async (req, res, next) => {
155 | const { email } = req.query;
156 | // 这里必须要await
157 | let result = await UserModel.deleteUser(email);
158 | if (result.acknowledged && result.deletedCount != 0) {
159 | res.send({
160 | msg: '用户注销成功!',
161 | status: 200,
162 | });
163 | } else {
164 | res.send({
165 | msg: '用户注销失败!',
166 | status: 0,
167 | });
168 | }
169 | };
170 |
171 | module.exports = {
172 | login,
173 | logout,
174 | getUserState,
175 | updateUserInfo,
176 | getUsers,
177 | register,
178 | deleteUser,
179 | updatePassword,
180 | };
181 |
--------------------------------------------------------------------------------
/MyBlogServe/db/connect.js:
--------------------------------------------------------------------------------
1 | const mongoose = require('mongoose');
2 | // 连接数据库
3 | mongoose.connect('mongodb://localhost:27017/MyBlog', (err) => {
4 | if (err) {
5 | console.log('数据库链接失败!');
6 | // console.log(err)
7 | } else {
8 | console.log('数据库链接成功!');
9 | }
10 | });
11 |
12 |
--------------------------------------------------------------------------------
/MyBlogServe/keys/rsa_private_key.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEowIBAAKCAQEAv/s8O3PlaGwc9EeABBC3coaAfKOle4H2d+64bXwA84IWGKPQ
3 | Xvsvx+viTlCovicvEMuP3di8JURMURJT0hJ37VYgHZNBhjOI5f8gyXa+JjtCtbaH
4 | tMogRestNhFhSLtQm9QY/pVotPgT9khkf4fJMhRsZOGmeEsKK2ALXwdHGveY1RdB
5 | uzny+9xogAFW5CVSWyeAYq7YRrIqdx5LmqBstmcv+VKBMzM4rySbtc9fAO+Oyr3Z
6 | DnLAStntB3nKaCDj657mHn8YBi1dUcxTe9aSuhAlV25mReQOquu5uakpz6WV3afk
7 | Fd2blqe2qRUjH8cQaLkGONDLBisIuEJf+kGkvQIDAQABAoIBAGw/o/m94pebhkPy
8 | 4Orp5hZMYrxkpZVbdXawgwswxXSIYB8qlv5HUey/Q453Cn6Vp4Mn1In5gDTfKsz3
9 | sY2c3kRTsK4cbvDVtBZDYeBW9OanuXiuYBx/b+0cqxR2fk09WTlUQXejFTQdQVw3
10 | +3qxPK/hNjE3zt67KRPGBwNhHiXEhVfIZ+fNPaHhF7lK2Zs5RZJdonaIOS20wpsR
11 | rPqGkS+s/x00Iyrn6rBBWsW09VunS04ELudzPBICKBMRuhdSm8C0zQmrzWQtS8kq
12 | jYN4cDJU0dMCMIgnYUbvsCq+I6FRfNIOsur14rWn+/Kgu/P2XdysqLn/5DvPCr/d
13 | GtG0eF0CgYEA8aqspis5igODdcptf+kkI3saDVyKzyGR7z0e3HuzroIf+rioyNjp
14 | R4sXdQLnwB4loKQX+0YsLPBLVQKCTA7tGn6dMQQ/i5OEb+bWwrm9h8UPPCXKWnGm
15 | k1zVC/zqaORGMg+6ntPxHjwvBn8Snvk+OMoa5ZgJl7isgELzK3NwFFMCgYEAy14r
16 | EZwBno/mb4X5IXIu2h++mytBNdmfAabGXr/L5pICSRzrztjA9oXAsJLqF+iuBM8z
17 | 7wHWTu1OKJXh1h2JMrmWuXTwq0+fI4iwz2CwAAbV3GnYZS4u7/j5kVLfpNFC39ku
18 | R8namsWMYupxevr2wjg3KHHjFTX1emVHmARVQK8CgYEA0zY12q0ghsz3UjVvakGb
19 | Qh9O76qX7twKLaufk1fR/Izh4kEN0ywxBkQ8Zhn57mDqxfFkvEniRgxl6pBczJin
20 | BWbvf22VFCoDr8FypZGsYkMKQ6lLp6x4x4Z09RtAzBfmec5hbnsR2zkCaI0a+zIe
21 | /Yc15r/wclgG+7qHyMwFgt0CgYAddsQ4peiaJ3EUYU2p6dgd5BGCe67T9XaTD62X
22 | 1qPdAPRx0U3cxwyV6uTy8CYYVq63pal5jEOXZcw4FxcEJX1WKwtKTUX9G+kLhedP
23 | 9EsrhdIAQBmI9zr3q5PE2UPrpiHROq742abhW5OuVRch4TBVDT34jx9+WDX7iKbp
24 | wF71owKBgAIlsZw06TLkVHSpOmJa4dv8w/ojZp5p4yVmNSb+6DcupJt4b8kBiN/r
25 | 2BY8bvBS9zUrAgNfB3h4CDNjTk7NLaSTdBD5raSjjPqKt0wzpOe7Hxq2wHKpGcVt
26 | E+0nFO89X3HqVvC/gPSAPEJgKDWinbAX+roTJ6mqbHio+WSZ++RT
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/MyBlogServe/keys/rsa_public_key.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv/s8O3PlaGwc9EeABBC3
3 | coaAfKOle4H2d+64bXwA84IWGKPQXvsvx+viTlCovicvEMuP3di8JURMURJT0hJ3
4 | 7VYgHZNBhjOI5f8gyXa+JjtCtbaHtMogRestNhFhSLtQm9QY/pVotPgT9khkf4fJ
5 | MhRsZOGmeEsKK2ALXwdHGveY1RdBuzny+9xogAFW5CVSWyeAYq7YRrIqdx5LmqBs
6 | tmcv+VKBMzM4rySbtc9fAO+Oyr3ZDnLAStntB3nKaCDj657mHn8YBi1dUcxTe9aS
7 | uhAlV25mReQOquu5uakpz6WV3afkFd2blqe2qRUjH8cQaLkGONDLBisIuEJf+kGk
8 | vQIDAQAB
9 | -----END PUBLIC KEY-----
10 |
--------------------------------------------------------------------------------
/MyBlogServe/model/blogs.js:
--------------------------------------------------------------------------------
1 | const mongoose = require('mongoose');
2 | const BlogSchema = new mongoose.Schema({
3 | //创建博客模型
4 | date: { type: Date }, //创建日期
5 | title: { type: String, require: true },
6 | classification: { type: mongoose.Types.ObjectId, require: true }, //所属专栏
7 | favour: [
8 | {
9 | type: String,
10 | },
11 | ], //点赞的浏览器指纹数组
12 | tags: [
13 | {
14 | type: mongoose.Types.ObjectId,
15 | require: true,
16 | },
17 | ],
18 | browse: { type: Number, default: 0 },
19 | content: { type: String, require: true },
20 | digest: { type: String }, // 描述信息
21 | state: { type: Boolean, default: false }, // 状态:是否发布
22 | });
23 | const BlogModel = mongoose.model('blogs', BlogSchema);
24 | // 新增文章
25 | const addblog = data => {
26 | let article = new BlogModel(data);
27 | return article
28 | .save()
29 | .then(res => {
30 | return true;
31 | })
32 | .catch(() => {
33 | return false;
34 | });
35 | };
36 | // 更新博客内容
37 | const updateBlog = (_id, content, digest, title, tags) => {
38 | console.log(tags);
39 | return BlogModel.updateOne({ _id }, { $set: { content, title, digest, tags } });
40 | };
41 | // 修改博客状态
42 | const changeBlogState = (state, id) => {
43 | // return BlogModel.updateOne(id, { $set: { state } });
44 | return BlogModel.updateOne({ _id: id }, { $set: { state } });
45 | };
46 | // 删除博客
47 | const deleteBlog = _id => {
48 | return BlogModel.deleteOne({ _id }).lean();
49 | };
50 | // 查询某一博客
51 | const getBlog = id => {
52 | return BlogModel.findById(id).lean();
53 | // return BlogModel.aggregate([
54 | // {
55 | // $lookup: {
56 | // from: 'classifies', // 关联 articles 表
57 | // localField: 'classification', // 根据 comments 里 articleId 字段查询
58 | // foreignField: '_id', // 查找 articles 表里对应的 _id 的数据
59 | // pipeline: [{ $project: { title: 1 } }],
60 | // as: 'classify', // 返回的字段别名
61 | // },
62 | // },
63 | // { $match: { _id: id } },
64 | // { $unwind: '$userinfo' }, //数据打散
65 | // ]);
66 | };
67 | // 查询所有文章
68 | const getBlogs = () => {
69 | return BlogModel.find().sort({ date: -1 }).lean();
70 | };
71 | // 查询所有已发布的博客
72 | const getPublishBlogs = (pageStart = 0, pageSize = 5) => {
73 | return BlogModel.find({ state: true }, '_id date digest favour title browse classification').skip(pageStart).limit(pageSize).lean();
74 | };
75 | // 查询所有已发布的博客的数量
76 | const getblogSums = () => {
77 | return BlogModel.find({ state: true }).count();
78 | };
79 | // 查询某一专栏下的所有博客
80 | const getBlogsOfClassify = classification => {
81 | return BlogModel.find({ classification, state: true }, '_id date digest favour title browse').lean();
82 | };
83 | // 查询某一书签下的所有博客
84 | const getBlogsOfTag = searchTag => {
85 | return BlogModel.find({ tags: { $in: searchTag } }, '_id date digest favour title browse').lean();
86 | };
87 | // 增加点赞
88 | const addFavour = (id, favourMurmur) => {
89 | return BlogModel.findByIdAndUpdate(id, { $push: { favour: favourMurmur } });
90 | };
91 | // 获取点赞数
92 | const getFavour = _id => {
93 | return BlogModel.findById(_id, 'favour');
94 | };
95 | // 增加浏览量
96 | const addBlogBrowse = _id => {
97 | return BlogModel.updateOne({ _id }, { $inc: { browse: 1 } });
98 | };
99 | // 模糊查询所有文章
100 | const searchBlogs = searchValue => {
101 | let regexp = new RegExp(searchValue, 'i');
102 | return BlogModel.find({
103 | $or: [{ title: { $regex: regexp } }],
104 | state: true,
105 | }).lean();
106 | };
107 | module.exports = {
108 | addblog,
109 | updateBlog,
110 | changeBlogState,
111 | deleteBlog,
112 | getBlog,
113 | getBlogs,
114 | getPublishBlogs,
115 | getblogSums,
116 | getBlogsOfClassify,
117 | addFavour,
118 | addBlogBrowse,
119 | getFavour,
120 | searchBlogs,
121 | getBlogsOfTag,
122 | };
123 |
--------------------------------------------------------------------------------
/MyBlogServe/model/classifies.js:
--------------------------------------------------------------------------------
1 | // 专栏数据模型
2 | const mongoose = require('mongoose');
3 | const ClassifySchema = new mongoose.Schema({
4 | //创建表
5 | date: { type: Date },
6 | title: { type: String },
7 | digest: { type: String }, // 描述信息
8 | articleNum: { type: Number, default: 0 }, // 文章数量
9 | bgColor: { type: String },
10 | });
11 | const ClassifyModel = mongoose.model('classify', ClassifySchema);
12 | // 新增专栏
13 | const addClassify = data => {
14 | const Classify = new ClassifyModel(data);
15 | return Classify.save()
16 | .then(() => {
17 | return true;
18 | })
19 | .catch(() => {
20 | return false;
21 | });
22 | };
23 | // 查询某一专栏信息
24 | const getClassify = id => {
25 | return ClassifyModel.findById(id);
26 | };
27 | // 数据面板需要数据
28 | const getClassifyForDataBoard = () => {
29 | return ClassifyModel.find({},'title articleNum');
30 | };
31 | // 删除专栏
32 | const deleteClassify = _id => {
33 | return ClassifyModel.deleteOne({ _id });
34 | };
35 | // 更新某一专栏文章数量
36 | const updateClassifySum = (_id, num) => {
37 | return ClassifyModel.updateOne({ _id }, { $inc: { articleNum: num } });
38 | };
39 | // 更新某一专栏
40 | const updateClassifyTitle = (_id, title, digest) => {
41 | return ClassifyModel.updateOne({ _id }, { $set: { title, digest } });
42 | };
43 | // 查询所有专栏
44 | const getClassifies = () => {
45 | return ClassifyModel.find().lean();
46 | };
47 | // 查询所有专栏的数量
48 | const getClassifySums = () => {
49 | return ClassifyModel.count();
50 | };
51 | module.exports = {
52 | addClassify,
53 | deleteClassify,
54 | getClassifies,
55 | updateClassifySum,
56 | getClassify,
57 | updateClassifyTitle,
58 | getClassifySums,
59 | getClassifyForDataBoard
60 | };
61 |
--------------------------------------------------------------------------------
/MyBlogServe/model/comments.js:
--------------------------------------------------------------------------------
1 | const mongoose = require('mongoose');
2 | const CommentSchema = new mongoose.Schema({
3 | //创建博客模型
4 | date: { type: Date, require: true }, //创建日期
5 | keyId: { type: String, require: true }, // 评论的文章id
6 | articleTitle: { type: String, require: true },
7 | favour: [
8 | {
9 | type: String,
10 | },
11 | ],
12 | content: { type: String, default: '' },
13 | murmur: { type: String, require: true },
14 | replyInfo: [
15 | {
16 | date: { type: Date, require: true }, //创建日期
17 | // replymurmur: { type: String, require: true },// 回复的指纹
18 | // replyId: { type: mongoose.Types.ObjectId, require: true }, // 回复的id
19 | replyName: { type: String, require: true },
20 | // username: { type: String, require: true },
21 | favour: [
22 | {
23 | type: String,
24 | },
25 | ],
26 | reply: { type: String, default: '' },
27 | murmur: { type: String, require: true }, // 当前此条回复的指纹
28 | },
29 | ],
30 | });
31 |
32 | const CommentModel = mongoose.model('comment', CommentSchema);
33 | // 新增一级评论
34 | const addFirstComment = data => {
35 | let comment = new CommentModel(data);
36 | return comment
37 | .save()
38 | .then(res => res)
39 | .catch(err => {
40 | return false;
41 | });
42 | };
43 | // 新增次级评论
44 | const addSecondComment = (_id, reply) => {
45 | return CommentModel.updateOne({ _id }, { $push: { replyInfo: reply } });
46 | };
47 | // 给一级评论点赞
48 | const addFirstFavour = (_id, favourMurmur) => {
49 | return CommentModel.updateOne({ _id }, { $push: { favour: favourMurmur } });
50 | };
51 | // // 给次级评论点赞
52 | const addSecondFavour = async (_id, replyId, favourMurmur) => {
53 | return CommentModel.updateOne({ _id, replyInfo: { $elemMatch: { _id: replyId } } }, { $push: { 'replyInfo.$.favour': favourMurmur } });
54 | };
55 | // 删除一级评论
56 | const deleteFirstComment = _id => {
57 | return CommentModel.deleteOne({ _id });
58 | };
59 | // 删除次级评论
60 | const deleteSecondComment = (_id, replyId) => {
61 | return CommentModel.updateOne({ _id }, { $pull: { replyInfo: { _id: replyId } } });
62 | };
63 | // 查询所有评论
64 | const getCommentsOfArticle = (_id, pageSize = 5, pageStart = 0) => {
65 | return CommentModel.find({ keyId: _id }).skip(pageStart).limit(pageSize).lean();
66 | };
67 | const getComments = (pageSize = 5, pageStart = 0) => {
68 | return CommentModel.find().lean();
69 | // return CommentModel.aggregate([
70 | // {
71 | // $lookup: {
72 | // from: "murmurs", // 关联 articles 表
73 | // localField: "murmur", // 根据 comments 里 articleId 字段查询
74 | // foreignField: "murmur", // 查找 articles 表里对应的 _id 的数据
75 | // pipeline: [ {$project: {username: 1} } ],
76 | // as: "userinfo",// 返回的字段别名
77 | // },
78 | // },
79 | // { $unwind: "$userinfo" },//数据打散
80 | // ]);
81 | // .skip(pageStart).limit(pageSize).lean();
82 | };
83 | // 查询某一个评论
84 | const getCommentReplyLast = id => {
85 | return CommentModel.findById(id);
86 | };
87 |
88 | module.exports = {
89 | addFirstComment,
90 | addSecondComment,
91 | addFirstFavour,
92 | deleteFirstComment,
93 | deleteSecondComment,
94 | getComments,
95 | addSecondFavour,
96 | getCommentReplyLast,
97 | getCommentsOfArticle,
98 | };
99 |
--------------------------------------------------------------------------------
/MyBlogServe/model/jottings.js:
--------------------------------------------------------------------------------
1 | // 随笔数据模型
2 | const mongoose = require('mongoose');
3 | const JottingSchema = new mongoose.Schema({
4 | //创建表
5 | date: { type: Date },
6 | title: { type: String, require: true },
7 | favour: [
8 | {
9 | type: String,
10 | default: 0,
11 | },
12 | ],
13 | tags: [
14 | {
15 | type: mongoose.Types.ObjectId,
16 | require: true,
17 | },
18 | ],
19 | browse: { type: Number, default: 0 },
20 | content: { type: String, require: true },
21 | digest: { type: String }, // 描述信息
22 | state: { type: Boolean, default: false }, // 状态:是否发布
23 | });
24 | const JottingModel = mongoose.model('jotting', JottingSchema);
25 | // 新增随笔
26 | const addJotting = data => {
27 | let jotting = new JottingModel(data);
28 | return jotting
29 | .save()
30 | .then(() => {
31 | return true;
32 | })
33 | .catch(() => {
34 | return false;
35 | });
36 | };
37 | // 更新随笔
38 | const updateJotting = (_id, { content, digest, title, tags }) => {
39 | return JottingModel.updateOne({ _id }, { $set: { content, digest, title, tags } });
40 | };
41 | // 修改随笔状态
42 | const changeJottingState = (state, _id) => {
43 | return JottingModel.updateOne({ _id }, { $set: { state } });
44 | };
45 | // 删除随笔
46 | const deleteJotting = _id => {
47 | return JottingModel.deleteOne({ _id });
48 | };
49 | // 查询某一随笔
50 | const getJotting = id => {
51 | return JottingModel.findById(id).lean();
52 | };
53 | // 查询所有随笔
54 | const getJottings = () => {
55 | return JottingModel.find().sort({date:-1}).lean();
56 | };
57 | // 查询所有已发布随笔
58 | const getPublishJottings = (pageStart = 0, pageSize = 5) => {
59 | return JottingModel.find({ state: true }, '_id date digest favour title browse').skip(pageStart).limit(pageSize).lean();
60 | };
61 | // 查询某一书签下的所有博客
62 | const getJottingsOfTag = searchTag => {
63 | return JottingModel.find({ tags: { $in: searchTag } }, '_id date digest favour title browse').lean();
64 | };
65 | // 查询所有已发布的随笔数量
66 | const getJottingSums = () => {
67 | return JottingModel.find({ state: true }).count();
68 | };
69 | // 增加点赞
70 | const addFavour = (_id, favourMurmur) => {
71 | return JottingModel.updateOne({ _id }, { $push: { favour: favourMurmur } });
72 | };
73 | // 获取点赞数
74 | const getFavour = id => {
75 | return JottingModel.findById(id, 'favour');
76 | };
77 | // 增加浏览量
78 | const addJottingBrowse = _id => {
79 | return JottingModel.updateOne({ _id }, { $inc: { browse: 1 } });
80 | };
81 | // 模糊查询所有随笔
82 | const searchJottings = searchValue => {
83 | let regexp = new RegExp(searchValue, 'i');
84 | return JottingModel.find({
85 | $or: [{ title: { $regex: regexp } }],
86 | state: true,
87 | }).lean();
88 | };
89 | module.exports = {
90 | addJotting,
91 | updateJotting,
92 | changeJottingState,
93 | deleteJotting,
94 | getJotting,
95 | getJottings,
96 | getPublishJottings,
97 | getJottingSums,
98 | addJottingBrowse,
99 | addFavour,
100 | getFavour,
101 | searchJottings,
102 | getJottingsOfTag,
103 | };
104 |
--------------------------------------------------------------------------------
/MyBlogServe/model/murmurs.js:
--------------------------------------------------------------------------------
1 | const mongoose = require('mongoose');
2 | const MurmurSchema = new mongoose.Schema({
3 | date: { type: Date, require: true },
4 | username: { type: String, require: true },
5 | murmur: { type: String, require: true, unique: true },
6 | avatarUrl: { type: String },
7 | });
8 | const MurmurModel = mongoose.model('murmur', MurmurSchema);
9 |
10 | /**
11 | *新增浏览器指纹信息
12 | * @param {object} data 浏览器指纹的相关信息
13 | * @return 成功返回新增的指纹信息,否则返回false
14 | */
15 | const addMurmur = data => {
16 | const murmur = new MurmurModel(data);
17 | return murmur
18 | .save()
19 | .then(res => res)
20 | .catch(() => false);
21 | };
22 |
23 | /**
24 | *修改浏览器指纹对应用户名
25 | * @param {string} murmur 浏览器指纹
26 | * @param {string} username 浏览器指纹对应用户名
27 | */
28 | const updateMurmurUsername = (murmur, username) => {
29 | return MurmurModel.updateOne({ murmur }, { $set: { username } });
30 | };
31 |
32 | /**
33 | *更新用户头像
34 | * @param {string} murmur 浏览器指纹
35 | * @param {string} avatarUrl 浏览器指纹对应头像地址
36 | */
37 | const updateMurmurAvatar = (murmur, avatarUrl) => {
38 | return MurmurModel.updateOne({ murmur }, { $set: { avatarUrl } });
39 | };
40 |
41 | // // 删除用户
42 | const deleteMurmurInfo = id => {
43 | return MurmurModel.deleteOne({ _id: id });
44 | };
45 | // 查找某一个用户,如果用户信息不存在返回null
46 |
47 | /**
48 | * @param {string} murmur 浏览器指纹
49 | * @return {object} 查找到的指纹信息
50 | */
51 | const getMurmurInfo = murmur => {
52 | return MurmurModel.findOne({ murmur });
53 | };
54 |
55 | /**
56 | *获取所有指纹信息
57 | @return {Array} 查找到的指纹信息对象数组
58 | */
59 | const getMurmurInfos = () => {
60 | return MurmurModel.find().lean();
61 | };
62 | module.exports = {
63 | addMurmur,
64 | getMurmurInfo,
65 | updateMurmurUsername,
66 | updateMurmurAvatar,
67 | getMurmurInfos,
68 | deleteMurmurInfo,
69 | };
70 |
--------------------------------------------------------------------------------
/MyBlogServe/model/photo.js:
--------------------------------------------------------------------------------
1 | const mongoose = require('mongoose');
2 | const PhotoSchema = new mongoose.Schema({
3 | uploadTime: { type: Date, require: true },
4 | shootingTime: { type: String, required: true },
5 | digest: { type: String, required: true },
6 | photoUrl: { type: String, required: true, unique: true },
7 | thumbnailUrl: { type: String },
8 | preBg: { type: String },
9 | });
10 | const PhotoModel = mongoose.model('Photo', PhotoSchema);
11 |
12 | /**
13 | *新增照片
14 | * @param {object} data 照片的相关信息
15 | * @return 成功返回新增的照片信息,否则返回false
16 | */
17 | const addPhoto = data => {
18 | console.log(data);
19 | const Photo = new PhotoModel(data);
20 | return Photo.save()
21 | .then(res => res)
22 | .catch(err => false);
23 | };
24 |
25 | /**
26 | *删除照片
27 | * @param {string} _id
28 | */
29 | const deletePhoto = _id => {
30 | return PhotoModel.deleteOne({ _id });
31 | };
32 |
33 | /**
34 | * 查找某一个照片
35 | * @param {string} id 照片的_id
36 | * @return {object} 查找到的照片
37 | */
38 | const getPhoto = id => {
39 | return PhotoModel.findById(id);
40 | };
41 | /**
42 | * 更新某一个照片
43 | * @param {string} id 照片的_id
44 | * @param {string} digest 新的描述信息
45 | * @return {object} 更新操作结果
46 | */
47 | const updatePhoto = (_id, digest, shootingTime) => {
48 | return PhotoModel.updateOne({ _id }, { $set: { digest, shootingTime } });
49 | };
50 | /**
51 | *获取所有照片
52 | @return {Array} 查找到的照片对象数组
53 | */
54 | const getPhotos = () => {
55 | return PhotoModel.find().lean();
56 | };
57 |
58 | /**
59 | *获取所有照片的数量
60 | * @return {number} 照片数量
61 | */
62 | const getPhotoSums = () => {
63 | return PhotoModel.count();
64 | };
65 |
66 | module.exports = {
67 | getPhotos,
68 | getPhoto,
69 | deletePhoto,
70 | addPhoto,
71 | getPhotoSums,
72 | updatePhoto,
73 | };
74 |
--------------------------------------------------------------------------------
/MyBlogServe/model/routes.js:
--------------------------------------------------------------------------------
1 | const mongoose = require('mongoose');
2 | const RouteSchema = new mongoose.Schema({
3 | //创建表
4 | path: { type: String, require: true, unique: true },
5 | name: { type: String },
6 | meta: { type: Object, default: {} },
7 | // children: [
8 | // {
9 | // path: { type: String,unique: true },
10 | // name: { type: String },
11 | // meta: { type: Object, default: {} },
12 | // limits: [
13 | // {
14 | // type: String,
15 | // },
16 | // ],
17 | // component: { type: String }, //index: { unique: true }
18 | // },
19 | // ],
20 | limits: [
21 | {
22 | type: String,
23 | require: true,
24 | },
25 | ],
26 | component: { type: String }, //index: { unique: true }
27 | });
28 |
29 | const RouteModel = mongoose.model('route', RouteSchema);
30 | // 新增一级路由
31 | const addFirstRoute = route => {
32 | const user = new RouteModel(route);
33 | return user
34 | .save()
35 | .then(() => true)
36 | .catch(() => false);
37 | };
38 | // 新增二级路由
39 | const addSecondRoute = (parentRouteName, route) => {
40 | return RouteModel.updateOne({ name: parentRouteName }, { $push: { children: route } });
41 | };
42 | // 更新一级路由信息
43 | const updateFirstRouteInfo = ({ _id, name, path, component, limits }) => {
44 | return RouteModel.updateOne({ _id }, { $set: { name, path, component, limits } });
45 | };
46 | // 更新二级路由信息
47 | const updateSecondRouteInfo = ({ _id, path, name, component, limits }) => {
48 | return RouteModel.updateOne({ _id, children: { $elemMatch: { path } } }, { $set: { name, component, limits } });
49 | };
50 | // 删除一级路由
51 | const deleteFirstRoute = _id => {
52 | return RouteModel.deleteOne({ _id });
53 | };
54 | // 删除二级路由
55 | const deleteSecondRoute = (id, path) => {
56 | return RouteModel.findByIdAndUpdate(id, { $pull: { children: { path } } });
57 | };
58 | // 查找所有路由
59 | const getRoutes = () => {
60 | return RouteModel.find();
61 | };
62 | // 根据path查找路由
63 | const getRouteByPath = path => {
64 | return RouteModel.findOne({ path });
65 | };
66 |
67 | module.exports = {
68 | addFirstRoute,
69 | addSecondRoute,
70 | updateFirstRouteInfo,
71 | updateSecondRouteInfo,
72 | deleteFirstRoute,
73 | deleteSecondRoute,
74 | getRoutes,
75 | getRouteByPath,
76 | };
77 |
--------------------------------------------------------------------------------
/MyBlogServe/model/tag.js:
--------------------------------------------------------------------------------
1 | const mongoose = require('mongoose');
2 | const TagSchema = new mongoose.Schema({
3 | date: { type: Date, require: true },
4 | title: { type: String, require: true, unique: true },
5 | digest: { type: String, require: true },
6 | bg: { type: String },
7 | });
8 | const TagModel = mongoose.model('tag', TagSchema);
9 |
10 | /**
11 | *新增标签
12 | * @param {object} data 标签的相关信息
13 | * @return 成功返回新增的标签信息,否则返回false
14 | */
15 | const addTag = data => {
16 | const tag = new TagModel(data);
17 | return tag
18 | .save()
19 | .then(res => res)
20 | .catch(() => false);
21 | };
22 |
23 | /**
24 | *删除标签
25 | * @param {string} murmur 浏览器指纹
26 | */
27 | const deleteTag = _id => {
28 | return TagModel.deleteOne({ _id });
29 | };
30 |
31 | /**
32 | * 查找某一个标签
33 | * @param {string} id 标签的_id
34 | * @return {object} 查找到的标签
35 | */
36 | const getTag = id => {
37 | return TagModel.findById(id);
38 | };
39 | /**
40 | * 查找某一个标签
41 | * @param {string} id 标签的_id
42 | * @return {object} 更新操作结果
43 | */
44 | const uptateTag = (_id, title, digest) => {
45 | console.log(_id, title, digest);
46 | return TagModel.updateOne({ _id }, { $set: { title, digest } });
47 | };
48 | /**
49 | *获取所有标签
50 | @return {Array} 查找到的标签对象数组
51 | */
52 | const getTags = () => {
53 | return TagModel.find().lean();
54 | };
55 | /**
56 | *获取所有标签的数量
57 | @return {number} 查找到的标签数量
58 | */
59 | const getTagSums = () => {
60 | return TagModel.count();
61 | };
62 |
63 | module.exports = {
64 | getTags,
65 | getTag,
66 | deleteTag,
67 | addTag,
68 | getTagSums,
69 | uptateTag,
70 | };
71 |
--------------------------------------------------------------------------------
/MyBlogServe/model/timeclue.js:
--------------------------------------------------------------------------------
1 | const mongoose = require('mongoose');
2 | const TimeclueSchema = new mongoose.Schema({
3 | date: { type: String },
4 | title: { type: String, require: true },
5 | state: { type: Boolean, require: true },
6 | digest: { type: String },
7 | });
8 | const TimeclueModel = mongoose.model('timeclue', TimeclueSchema);
9 | /**
10 | *新增时间线信息
11 | * @param {object} data 时间线信息的相关信息
12 | * @return 成功返回新增的时间线信息信息,否则返回false
13 | */
14 | const addTimeclue = data => {
15 | const Timeclue = new TimeclueModel(data);
16 | return Timeclue.save()
17 | .then(res => res)
18 | .catch(() => false);
19 | };
20 |
21 | /**
22 | *删除时间线信息
23 | * @param {string} murmur 浏览器指纹
24 | */
25 | const deleteTimeclue = _id => {
26 | return TimeclueModel.deleteOne({ _id });
27 | };
28 |
29 | /**
30 | * 查找某一个时间线信息
31 | * @param {string} id 时间线信息的_id
32 | * @return {object} 查找到的时间线信息
33 | */
34 | const getTimeclue = id => {
35 | return TimeclueModel.findById(id);
36 | };
37 | /**
38 | * 查找某一个时间线信息
39 | * @param {string} id 时间线信息的_id
40 | * @return {object} 更新操作结果
41 | */
42 | const uptateTimeclue = (id, date, title, digest) => {
43 | return TimeclueModel.updateOne({ _id: id }, { $set: { date, title, digest } });
44 | };
45 | const changeTimeNodeState = (id, state) => {
46 | return TimeclueModel.updateOne({ _id: id }, { $set: { state } });
47 | };
48 | /**
49 | *获取所有时间线信息
50 | @return {Array} 查找到的时间线信息对象数组
51 | */
52 | const getTimeclues = () => {
53 | return TimeclueModel.find().sort({ date: -1 }).lean();
54 | };
55 | /**
56 | *获取所有时间线信息的数量
57 | @return {number} 查找到的时间线信息数量
58 | */
59 | // const getTimeclueSums = () => {
60 | // return TimeclueModel.count();
61 | // };
62 |
63 | module.exports = {
64 | getTimeclues,
65 | getTimeclue,
66 | deleteTimeclue,
67 | addTimeclue,
68 | // getTimeclueSums,
69 | uptateTimeclue,
70 | changeTimeNodeState,
71 | };
72 |
--------------------------------------------------------------------------------
/MyBlogServe/model/users.js:
--------------------------------------------------------------------------------
1 | const mongoose = require('mongoose');
2 |
3 | const UserSchema = new mongoose.Schema({
4 | //创建表
5 | username: { type: String, require: true },
6 | password: { type: String, require: true },
7 | email: { type: String, require: true, unique: true }, //index: { unique: true }
8 | date: { type: Date },
9 | avatarUrl: { type: String },
10 | role: { type: String, require: true, default: '普通用户' },
11 | });
12 | const UserModel = mongoose.model('user', UserSchema);
13 | // 新增用户
14 | const addUser = data => {
15 | const user = new UserModel(data);
16 | return user
17 | .save()
18 | .then(() => true)
19 | .catch(() => false);
20 | };
21 | const uploadAvatar = (email, avatarUrl) => {
22 | return UserModel.updateOne({ email }, { $set: { avatarUrl } });
23 | };
24 | // 更新用户信息
25 | const updateUserInfo = (email, role, username) => {
26 | return UserModel.updateOne({ email }, { $set: { username, role } });
27 | };
28 | // 更新用户信息
29 | const updatePassword = (email, password) => {
30 | return UserModel.updateOne({ email }, { $set: { password } });
31 | };
32 | // 删除用户
33 | const deleteUser = email => {
34 | return UserModel.deleteOne({ email });
35 | };
36 | // 查找某一个用户,如果用户信息不存在返回null
37 | const getUser = email => {
38 | return UserModel.findOne({ email });
39 | };
40 | // 查询所有用户
41 | const getUsers = () => {
42 | return UserModel.find().lean();
43 | };
44 | module.exports = {
45 | addUser,
46 | updateUserInfo,
47 | getUsers,
48 | deleteUser,
49 | getUser,
50 | updatePassword,
51 | uploadAvatar,
52 | };
53 |
--------------------------------------------------------------------------------
/MyBlogServe/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "myblogserve",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "nodemon ./bin/www"
7 | },
8 | "dependencies": {
9 | "bcrypt": "^5.0.1",
10 | "connect-multiparty": "^2.2.0",
11 | "cookie-parser": "~1.4.4",
12 | "debug": "~2.6.9",
13 | "express": "~4.16.1",
14 | "express-session": "^1.17.2",
15 | "http-errors": "~1.6.3",
16 | "jade": "~1.11.0",
17 | "jsonwebtoken": "^8.5.1",
18 | "mongoose": "^6.2.8",
19 | "morgan": "~1.9.1",
20 | "multer": "^1.4.5-lts.1",
21 | "nodemon": "^2.0.15"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/MyBlogServe/public/avatars/1661779453078:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogServe/public/avatars/1661779453078
--------------------------------------------------------------------------------
/MyBlogServe/public/avatars/1662256970035:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogServe/public/avatars/1662256970035
--------------------------------------------------------------------------------
/MyBlogServe/public/photos/1662046452834:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogServe/public/photos/1662046452834
--------------------------------------------------------------------------------
/MyBlogServe/public/photos/1662046521921:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogServe/public/photos/1662046521921
--------------------------------------------------------------------------------
/MyBlogServe/public/photos/1662046564119:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogServe/public/photos/1662046564119
--------------------------------------------------------------------------------
/MyBlogServe/public/photos/1662046595682:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogServe/public/photos/1662046595682
--------------------------------------------------------------------------------
/MyBlogServe/public/photos/1662047030636:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogServe/public/photos/1662047030636
--------------------------------------------------------------------------------
/MyBlogServe/public/photos/1662047054759:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogServe/public/photos/1662047054759
--------------------------------------------------------------------------------
/MyBlogServe/public/photos/1662047189170:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogServe/public/photos/1662047189170
--------------------------------------------------------------------------------
/MyBlogServe/public/photos/1662049020699:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogServe/public/photos/1662049020699
--------------------------------------------------------------------------------
/MyBlogServe/public/photos/1662049188808:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogServe/public/photos/1662049188808
--------------------------------------------------------------------------------
/MyBlogServe/public/photos/1662049270170:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogServe/public/photos/1662049270170
--------------------------------------------------------------------------------
/MyBlogServe/public/photos/1662049353519:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogServe/public/photos/1662049353519
--------------------------------------------------------------------------------
/MyBlogServe/public/photos/1662049446197:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogServe/public/photos/1662049446197
--------------------------------------------------------------------------------
/MyBlogServe/public/photos/1662049505602:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogServe/public/photos/1662049505602
--------------------------------------------------------------------------------
/MyBlogServe/public/photos/1662049548427:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogServe/public/photos/1662049548427
--------------------------------------------------------------------------------
/MyBlogServe/public/photos/1662049654510:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogServe/public/photos/1662049654510
--------------------------------------------------------------------------------
/MyBlogServe/public/photos/1662049758833:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogServe/public/photos/1662049758833
--------------------------------------------------------------------------------
/MyBlogServe/public/photos/1662049791176:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogServe/public/photos/1662049791176
--------------------------------------------------------------------------------
/MyBlogServe/public/photos/1662049883085:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogServe/public/photos/1662049883085
--------------------------------------------------------------------------------
/MyBlogServe/public/photos/1662050480857:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogServe/public/photos/1662050480857
--------------------------------------------------------------------------------
/MyBlogServe/public/photos/1662050583435:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/MyBlogServe/public/photos/1662050583435
--------------------------------------------------------------------------------
/MyBlogServe/public/stylesheets/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 50px;
3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
4 | }
5 |
6 | a {
7 | color: #00B7FF;
8 | }
9 |
--------------------------------------------------------------------------------
/MyBlogServe/routes/blogs.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var router = express.Router();
3 | var articleController = require('../controllers/blogs');
4 | /* GET users listing. */
5 | router.get('/getblogs', articleController.getBlogs);
6 | router.delete('/deleteblog', articleController.deleteBlog);
7 | router.post('/updateblog', articleController.updateBlog);
8 | router.post('/addblog', articleController.addBlog);
9 | router.get('/changeblogstate', articleController.changeBlogState);
10 | router.get('/getblog', articleController.getBlog);
11 | router.get('/getpublishblogs', articleController.getPublishBlogs);
12 | router.get('/getblogsofclassify', articleController.getBlogsOfClassify);
13 | router.get('/addfavour', articleController.addFavour);
14 | router.get('/addblogbrowse', articleController.addBlogBrowse);
15 | module.exports = router;
16 |
--------------------------------------------------------------------------------
/MyBlogServe/routes/classifies.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var router = express.Router();
3 | var classifyController = require('../controllers/classifies');
4 | /* GET users listing. */
5 | router.get('/getclassifies', classifyController.getClassifies);
6 | router.delete('/deleteclassify', classifyController.deleteClassify);
7 | router.post('/addclassify', classifyController.addClassify);
8 | router.post('/updateclassifytitle', classifyController.updateClassifyTitle)
9 | module.exports = router;
10 |
--------------------------------------------------------------------------------
/MyBlogServe/routes/comments.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var router = express.Router();
3 | var commentController = require('../controllers/comments');
4 | /* GET users listing. */
5 | router.post('/addfirstcomment', commentController.addFirstComment);
6 | router.post('/addsecondcomment', commentController.addSecondComment);
7 | router.delete('/deletefirstcomment', commentController.deleteFirstComment);
8 | router.delete('/deletesecondcomment', commentController.deleteSecondComment);
9 | router.get('/addfirstfavour', commentController.addFirstFavour);
10 | router.get('/addsecondfavour', commentController.addSecondFavour);
11 | router.get('/getcomments', commentController.getComments);
12 | router.get('/getcommentsofarticle', commentController.getCommentsOfArticle);
13 | module.exports = router;
14 |
--------------------------------------------------------------------------------
/MyBlogServe/routes/jottings.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var router = express.Router();
3 | var jottingController = require('../controllers/jottings');
4 | /* GET users listing. */
5 | router.get('/getjottings', jottingController.getJottings);
6 | router.delete('/deletejotting', jottingController.deleteJotting);
7 | router.post('/updatejotting', jottingController.updateJotting);
8 | router.post('/addjotting', jottingController.addJotting);
9 | router.get('/changestate', jottingController.changeState);
10 | router.get('/getpublishjottings', jottingController.getPublishJottings);
11 | router.get('/getjotting', jottingController.getJotting);
12 | router.get('/addfavour', jottingController.addFavour);
13 | router.get('/addjottingbrowse', jottingController.addJottingBrowse);
14 | module.exports = router;
15 |
--------------------------------------------------------------------------------
/MyBlogServe/routes/murmur.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var router = express.Router();
3 | var murmurController = require('../controllers/murmur');
4 |
5 | /* GET users listing. */
6 | router.post('/addmurmurinfo', murmurController.addMurmurInfo);
7 | router.post('/updatemurmurusername', murmurController.updateMurmurUsername);
8 | router.get('/getmurmurinfos', murmurController.getMurmurInfos);
9 | router.delete('/deletemurmurinfo', murmurController.deleteMurmurInfo);
10 | module.exports = router;
11 |
--------------------------------------------------------------------------------
/MyBlogServe/routes/photo.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var router = express.Router();
3 | var PhotoController = require('../controllers/photo');
4 | const multer = require('multer');
5 | const path = require('path');
6 | // 照片墙上传图片上传
7 | var storagePhoto = multer.diskStorage({
8 | // 配置文件上传后存储的路径
9 | destination: function (req, file, cb) {
10 | cb(null, path.join(__dirname, '../public/photos'));
11 | },
12 | // 配置文件上传后存储的路径和文件名
13 | filename: function (req, file, cb) {
14 | cb(null, Date.now() + path.extname(file.originalname));
15 | },
16 | });
17 | const uploadPhoto = multer({ storage: storagePhoto });
18 | /* GET users listing. */
19 | router.get('/getphotos', PhotoController.getPhotos);
20 | router.delete('/deletephoto', PhotoController.deletePhoto);
21 | router.post('/addphoto',uploadPhoto.single('photo'), PhotoController.addPhoto);
22 | router.post('/updatephotodigest', PhotoController.updatePhotoDigest)
23 | module.exports = router;
24 |
--------------------------------------------------------------------------------
/MyBlogServe/routes/routes.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var router = express.Router();
3 | var routeController = require('../controllers/routes');
4 | /* GET users listing. */
5 | router.post('/addfirstroute', routeController.addFirstRoute);
6 | router.post('/addsecondroute', routeController.addSecondRoute);
7 | router.post('/updatroute', routeController.updatRoute);
8 | router.get('/getroutes', routeController.getRoutes);
9 | router.get('/getroutelist', routeController.getRouteList);
10 | router.delete('/deleteroute', routeController.deleteRoute);
11 | module.exports = router;
12 |
--------------------------------------------------------------------------------
/MyBlogServe/routes/synthesis.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var router = express.Router();
3 | var synthesisControll = require('../controllers/synthesis');
4 | const multer = require('multer');
5 | const path = require('path');
6 | // markdown编辑文章上传图片
7 | var storageArtimg = multer.diskStorage({
8 | // 配置文件上传后存储的路径
9 | destination: function (req, file, cb) {
10 | cb(null, path.join(__dirname, '../public/images'));
11 | },
12 | // 配置文件上传后存储的路径和文件名
13 | filename: function (req, file, cb) {
14 | cb(null, Date.now() + path.extname(file.originalname));
15 | },
16 | });
17 | // 上传头像
18 | var storageAvatar = multer.diskStorage({
19 | // 配置文件上传后存储的路径
20 | destination: function (req, file, cb) {
21 | cb(null, path.join(__dirname, '../public/avatars'));
22 | },
23 | // 配置文件上传后存储的路径和文件名
24 | filename: function (req, file, cb) {
25 | cb(null, Date.now() + path.extname(file.originalname));
26 | },
27 | });
28 |
29 | const uploadArtimg = multer({ storage: storageArtimg });
30 | const uploadAvatar = multer({ storage: storageAvatar });
31 |
32 | router.get('/getwebinfo', synthesisControll.getWebInfo);
33 | router.get('/getsliderinfo', synthesisControll.getSliderInfo);
34 | router.get('/searcharticle', synthesisControll.searchArticle);
35 | router.post('/uploadartimg', uploadArtimg.single('artimg'), synthesisControll.uploadArtimg);
36 | router.post('/uploadavatar', uploadAvatar.single('avatar'), synthesisControll.uploadAvatar);
37 | router.get('/gettags', synthesisControll.getTags);
38 | router.get('/gettag', synthesisControll.getTag);
39 | router.delete('/deletetag', synthesisControll.deleteTag);
40 | router.post('/addtag', synthesisControll.addTag);
41 | router.post('/updatetag', synthesisControll.updateTag);
42 | router.get('/getarticlesoftag', synthesisControll.getArticlesOfTag);
43 | router.get('/getdatafordataboard', synthesisControll.getDataForDataBoard);
44 | module.exports = router;
45 |
--------------------------------------------------------------------------------
/MyBlogServe/routes/timeclue.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var router = express.Router();
3 | const TimeclueControll = require('../controllers/timeclue');
4 | router.get('/changetimenodestate', TimeclueControll.changeTimeNodeState);
5 | router.get('/gettimeclue', TimeclueControll.getTimeclue);
6 | router.get('/gettimeclues', TimeclueControll.getTimeclues);
7 | router.delete('/deletetimeclue', TimeclueControll.deleteTimeclue);
8 | router.post('/addtimeclue', TimeclueControll.addTimeclue);
9 | router.post('/updatetimeclue', TimeclueControll.updateTimeclue);
10 | module.exports = router;
11 |
--------------------------------------------------------------------------------
/MyBlogServe/routes/users.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var router = express.Router();
3 | var usersController = require('../controllers/users');
4 | /* GET users listing. */
5 | router.post('/login', usersController.login);
6 | router.get('/logout', usersController.logout);
7 | router.get('/getuserstate', usersController.getUserState);
8 | router.post('/updateuserinfo', usersController.updateUserInfo);
9 | router.get('/getusers', usersController.getUsers);
10 | router.post('/register', usersController.register);
11 | router.delete('/deleteuser', usersController.deleteUser);
12 | router.post('/updatepassword', usersController.updatePassword);
13 | module.exports = router;
14 |
--------------------------------------------------------------------------------
/MyBlogServe/views/error.jade:
--------------------------------------------------------------------------------
1 | extends layout
2 |
3 | block content
4 | h1= message
5 | h2= error.status
6 | pre #{error.stack}
7 |
--------------------------------------------------------------------------------
/MyBlogServe/views/index.jade:
--------------------------------------------------------------------------------
1 | extends layout
2 |
3 | block content
4 | h1= title
5 | p Welcome to #{title}
6 |
--------------------------------------------------------------------------------
/MyBlogServe/views/layout.jade:
--------------------------------------------------------------------------------
1 | doctype html
2 | html
3 | head
4 | title= title
5 | link(rel='stylesheet', href='/stylesheets/style.css')
6 | body
7 | block content
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 我的博客(MyBlog)
2 |
3 | ## 技术栈:vue2 + vuex + vue-router + axios + nodejs + express + mongodb + element-ui + echarts
4 |
5 | ## 项目介绍
6 |
7 | 本项目分为三个部分:后端接口、后台管理系统、前台系统,它们分别实现了
8 |
9 | 前台系统:博客展示、心情展示、瀑布流照片墙、留言板、时间线、关于、搜索、评论、专栏博客展示、书签文章展示、暗黑模式、头像上传
10 |
11 | 后台管理系统:权限管理、动态路由、登录、注册、文章管理、心情管理、专栏管理、书签管理、评论管理、照片管理、markdown 编辑文章、时间节点管理、路由管理、用户管理、数据看板
12 |
13 | 后端:MVC 模式使用 express 框架和 mongodb 数据库
14 |
15 | ## 性能优化:
16 |
17 | 1. 图片资源本地压缩,控制在 100kb 左右。
18 | 2. vue、element-ui、axios 采用 CDN 方式引入项目。
19 | 3. 开启 gzip 压缩,效果很明显,特别是项目上线后访问速度提高很多。
20 | 4. 优化了一些逻辑,减少了 http 请求。
21 | 5. 打包时不生成 map 文件(效果很明显)、将公共代码抽离、图片资源压缩(效果不是很明显)。
22 | 6. 在用户上传头像是使用 canvas 压缩后再上传,压缩效果很好。
23 |
24 | ## 使用体验优化
25 |
26 | 1. 前台系统首次加载白屏动画,切换路由使用过渡动画。
27 | 2. 多个页面使用 css 动画效果和平滑阴影给你更真实的体验。
28 | 3. 瀑布流照片墙,定宽不定高,给你极致体验。
29 | 4. 前台系统全局暗黑模式,更丰富的使用效果。
30 |
31 | ## 安装运行
32 |
33 | ### 导入数据库数据
34 |
35 | 我是使用 compass 可视化工具导出的,使用其他可视化工具导入可能略有不同,请自行百度导入。
36 |
37 | - 路由数据:`./MongodbData/routes.json`,若未导入则后台管理系统因没有路由数据将无法正常访问。
38 | - 时间线数据:`./MongodbData/timeclues.json`,此部分数据记录了项目的开发历程,可选
39 | - 用户数据:`./MongodbData/users.json`,用户数据,包含一个管理员与一个普通用户信息
40 | - 管理员账号:123@qq.com;密码:12345678
41 | - 普通用户:234@qq.com;密码:12345678
42 |
43 | ### 前台系统
44 |
45 | ```js
46 | // 安装依赖
47 | yarn
48 | // 运行
49 | yarn serve
50 | ```
51 |
52 | ### 后台管理系统
53 |
54 | ```js
55 | // 安装依赖
56 | yarn
57 | // 运行
58 | yarn serve
59 | ```
60 |
61 | ### 后端
62 |
63 | 连接 mongodb 数据库配置文件`db`,使用默认端口`27017`,数据库名称`MyBlog`
64 |
65 | ```js
66 | // 安装依赖
67 | yarn
68 | // 运行
69 | yarn start
70 | ```
71 |
72 | ## 效果展示
73 |
74 | ### 博客
75 | 
76 | ### 心情
77 | 
78 | ### 瀑布流照片墙
79 | 
80 | ### 留言板
81 | 
82 | ### 时间线
83 | 
84 | ### 关于
85 | 
86 | ### 文章管理
87 | 
88 | ### 照片管理
89 | 
90 | ### markdown编辑文章
91 | 
92 | ### 路由管理
93 | 
94 | ### 时间节点管理
95 | 
96 | ### 用户管理
97 | 
98 | ### 数据看板
99 | 
100 | ### 暗黑模式
101 | 
102 | ### 登录注册
103 | 
104 |
105 | # 结语
106 | 本项目还有很多可以继续完善的地方,你可以拉取本项目继续开发,不要忘了给个star哦!
--------------------------------------------------------------------------------
/ReadmeImg/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/ReadmeImg/1.png
--------------------------------------------------------------------------------
/ReadmeImg/10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/ReadmeImg/10.png
--------------------------------------------------------------------------------
/ReadmeImg/11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/ReadmeImg/11.png
--------------------------------------------------------------------------------
/ReadmeImg/12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/ReadmeImg/12.png
--------------------------------------------------------------------------------
/ReadmeImg/13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/ReadmeImg/13.png
--------------------------------------------------------------------------------
/ReadmeImg/14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/ReadmeImg/14.png
--------------------------------------------------------------------------------
/ReadmeImg/15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/ReadmeImg/15.png
--------------------------------------------------------------------------------
/ReadmeImg/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/ReadmeImg/2.png
--------------------------------------------------------------------------------
/ReadmeImg/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/ReadmeImg/3.png
--------------------------------------------------------------------------------
/ReadmeImg/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/ReadmeImg/4.png
--------------------------------------------------------------------------------
/ReadmeImg/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/ReadmeImg/5.png
--------------------------------------------------------------------------------
/ReadmeImg/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/ReadmeImg/6.png
--------------------------------------------------------------------------------
/ReadmeImg/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/ReadmeImg/7.png
--------------------------------------------------------------------------------
/ReadmeImg/8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/ReadmeImg/8.png
--------------------------------------------------------------------------------
/ReadmeImg/9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wind-Breaker1/MyBlog/b4c409fcb046709201b70a29ebdcd5f9a792b89e/ReadmeImg/9.png
--------------------------------------------------------------------------------
/default.conf:
--------------------------------------------------------------------------------
1 | server {
2 | listen 80;
3 | server_name localhost;
4 |
5 | #access_log /var/log/nginx/host.access.log main;
6 |
7 | location / {
8 | root /usr/share/nginx/html;
9 | index index.html index.htm;
10 | }
11 | # 反向代理
12 | location /api {
13 | proxy_pass http://127.0.0.1;
14 | }
15 | #error_page 404 /404.html;
16 |
17 | # redirect server error pages to the static page /50x.html
18 | #
19 | error_page 500 502 503 504 /50x.html;
20 | location = /50x.html {
21 | root /usr/share/nginx/html;
22 | }
23 |
24 | # proxy the PHP scripts to Apache listening on 127.0.0.1:80
25 | #
26 | # location ~ \.php$ {
27 | # proxy_pass http://127.0.0.1;
28 | # }
29 |
30 | # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
31 | #
32 | #location ~ \.php$ {
33 | # root html;
34 | # fastcgi_pass 127.0.0.1:9000;
35 | # fastcgi_index index.php;
36 | # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
37 | # include fastcgi_params;
38 | #}
39 |
40 | # deny access to .htaccess files, if Apache's document root
41 | # concurs with nginx's one
42 | #
43 | #location ~ /\.ht {
44 | # deny all;
45 | #}
46 | }
47 |
48 |
--------------------------------------------------------------------------------