├── .gitignore
├── README.md
├── babel.config.js
├── package-lock.json
├── package.json
├── public
├── favicon.ico
└── index.html
├── src
├── App.vue
├── api
│ ├── notebooks.js
│ ├── notes.js
│ ├── request.js
│ └── users.js
├── assets
│ └── css
│ │ ├── iconfont.css
│ │ ├── iconfont.js
│ │ ├── iconfont.ttf
│ │ └── style.css
├── components
│ ├── breadcrumb
│ │ └── BBreadcrumb.vue
│ ├── header
│ │ └── BHeader.vue
│ ├── note
│ │ └── Note.vue
│ └── notebook
│ │ └── Notebook.vue
├── main.js
├── reliance
│ ├── elementPlus.js
│ ├── mdEditor.js
│ ├── mdPreview.js
│ └── utils.js
├── router
│ └── index.js
├── store
│ └── index.js
├── utils
│ ├── htmlUtils.js
│ └── timeUtils.js
└── views
│ ├── admin
│ ├── Home.vue
│ ├── detail
│ │ └── Detail.vue
│ ├── list
│ │ ├── List.vue
│ │ └── components
│ │ │ └── columns.js
│ └── nList
│ │ ├── NList.vue
│ │ └── components
│ │ └── columns.js
│ └── user
│ ├── Home.vue
│ ├── Login.vue
│ ├── NotFound.vue
│ ├── detail
│ ├── Detail.vue
│ └── components
│ │ └── ToolBar.vue
│ ├── nDetail
│ ├── NDetail.vue
│ └── components
│ │ └── NoteTable.vue
│ ├── overview
│ ├── Overview.vue
│ └── components
│ │ ├── List.vue
│ │ ├── NList.vue
│ │ └── Profile.vue
│ └── search
│ ├── Search.vue
│ └── components
│ └── options.js
└── vue.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | pnpm-debug.log*
15 |
16 | # Editor directories and files
17 | .idea
18 | .vscode
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # rainforest-blog-frontend
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ["@vue/cli-plugin-babel/preset"],
3 | plugins: [
4 | [
5 | "import",
6 | {
7 | libraryName: "element-plus",
8 | customStyleName: (name) => {
9 | return `element-plus/lib/theme-chalk/${name}.css`;
10 | },
11 | },
12 | ],
13 | ],
14 | };
15 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rainforest-blog-frontend",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "vue-cli-service serve",
7 | "build": "vue-cli-service build --report",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "@kangc/v-md-editor": "^2.2.2",
12 | "axios": "^0.21.1",
13 | "core-js": "^3.6.5",
14 | "element-plus": "^1.0.2-beta.70",
15 | "highlight.js": "^10.7.2",
16 | "vue": "^3.0.0",
17 | "vue-router": "^4.0.0-0",
18 | "vuex": "^4.0.2"
19 | },
20 | "devDependencies": {
21 | "@vue/cli-plugin-babel": "~4.5.0",
22 | "@vue/cli-plugin-eslint": "~4.5.0",
23 | "@vue/cli-plugin-router": "~4.5.0",
24 | "@vue/cli-service": "~4.5.0",
25 | "@vue/compiler-sfc": "^3.0.0",
26 | "@vue/eslint-config-prettier": "^6.0.0",
27 | "babel-eslint": "^10.1.0",
28 | "babel-plugin-import": "^1.13.3",
29 | "compression-webpack-plugin": "^5.0.1",
30 | "eslint": "^6.7.2",
31 | "eslint-plugin-prettier": "^3.3.1",
32 | "eslint-plugin-vue": "^7.0.0",
33 | "node-sass": "^4.12.0",
34 | "prettier": "^2.2.1",
35 | "sass-loader": "^8.0.2"
36 | },
37 | "eslintConfig": {
38 | "root": true,
39 | "env": {
40 | "node": true
41 | },
42 | "extends": [
43 | "plugin:vue/vue3-essential",
44 | "eslint:recommended",
45 | "@vue/prettier"
46 | ],
47 | "parserOptions": {
48 | "parser": "babel-eslint"
49 | },
50 | "rules": {}
51 | },
52 | "browserslist": [
53 | "> 1%",
54 | "last 2 versions",
55 | "not dead"
56 | ],
57 | "_id": "rainforest-blog-frontend@0.1.0",
58 | "readme": "ERROR: No README data found!"
59 | }
60 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/inkmarkink/rainforest-blog-frontend/48dbec21f08f13e6b5657f158e58a2fdc82d34cf/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
13 |
--------------------------------------------------------------------------------
/src/api/notebooks.js:
--------------------------------------------------------------------------------
1 | import { request } from "./request";
2 |
3 | // 增加
4 | export function newNotebook(notebookData) {
5 | return request({
6 | url: "/notebook/new",
7 | method: "post",
8 | data: notebookData,
9 | });
10 | }
11 |
12 | // 删除
13 |
14 | // 修改
15 | export function updateNotebook(id, notebookData) {
16 | return request({
17 | url: `/notebook/update/${id}`,
18 | method: "patch",
19 | data: notebookData,
20 | });
21 | }
22 |
23 | // 查询单个
24 | export function getNotebookDetail(id) {
25 | return request({
26 | url: `/notebook/${id}`,
27 | method: "get",
28 | });
29 | }
30 |
31 | // 查询多个
32 | export function getNotebookList(queryData) {
33 | return request({
34 | url: "/notebook/list",
35 | method: "post",
36 | data: queryData,
37 | });
38 | }
39 |
--------------------------------------------------------------------------------
/src/api/notes.js:
--------------------------------------------------------------------------------
1 | import { request } from "./request";
2 |
3 | // 增加
4 | export function newNote(noteData) {
5 | return request({
6 | url: "/note/new",
7 | method: "post",
8 | data: noteData,
9 | });
10 | }
11 |
12 | // 删除
13 | export function deleteBlog(id, author) {
14 | return request({
15 | url: "/blog/del",
16 | method: "post",
17 | data: {
18 | id,
19 | author,
20 | },
21 | });
22 | }
23 |
24 | // 修改
25 | export function updateNote(id, noteData) {
26 | return request({
27 | url: `/note/${id}`,
28 | method: "patch",
29 | data: noteData,
30 | });
31 | }
32 |
33 | // 查询单个
34 | export function getNoteDetail(queryData) {
35 | return request({
36 | url: `/note/`,
37 | method: "post",
38 | data: queryData,
39 | });
40 | }
41 |
42 | // 查询多个
43 | export function getNoteList(queryData) {
44 | return request({
45 | url: "/note/list",
46 | method: "post",
47 | data: queryData,
48 | });
49 | }
50 |
--------------------------------------------------------------------------------
/src/api/request.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | // import router from "@/router";
3 | // import store from "@/store";
4 |
5 | export function request(config) {
6 | const instance = axios.create({
7 | baseURL: "/api",
8 | });
9 |
10 | // instance.interceptors.response.use((res) => {
11 | // // 拦截响应,做统一处理
12 | // if (res.data.code === 401) {
13 | // router.replace("/login");
14 | // store.commit("logout");
15 | // }
16 | // return res;
17 | // });
18 |
19 | return instance(config);
20 | }
21 |
--------------------------------------------------------------------------------
/src/api/users.js:
--------------------------------------------------------------------------------
1 | import { request } from "./request";
2 |
3 | export function login(userData) {
4 | return request({
5 | url: "/user/login",
6 | method: "post",
7 | data: userData,
8 | });
9 | }
10 |
--------------------------------------------------------------------------------
/src/assets/css/iconfont.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: "iconfont"; /* Project id */
3 | src: url('iconfont.ttf?t=1625158476472') format('truetype');
4 | }
5 |
6 | .iconfont {
7 | font-family: "iconfont" !important;
8 | font-size: 16px;
9 | font-style: normal;
10 | -webkit-font-smoothing: antialiased;
11 | -moz-osx-font-smoothing: grayscale;
12 | }
13 |
14 | .icon-comment:before {
15 | content: "\e62c";
16 | color: #ffd33d;
17 | }
18 |
19 | .icon-time:before {
20 | content: "\e61f";
21 | color: #d15704;
22 | }
23 |
24 | .icon-edit:before {
25 | content: "\e636";
26 | color: #fe898a;
27 | }
28 |
29 | .icon-add:before {
30 | content: "\e502";
31 | }
32 |
33 | .icon-file:before {
34 | content: "\e678";
35 | color: #00a1e3;
36 | }
37 |
38 | .icon-view:before {
39 | content: "\e609";
40 | color: #2166d6;
41 | }
42 |
43 | .icon-back:before {
44 | content: "\e639";
45 | color: #e34c26;
46 | }
47 |
48 | .icon-update:before {
49 | content: "\e6b6";
50 | color: #28a745;
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/src/assets/css/iconfont.js:
--------------------------------------------------------------------------------
1 | !function(e){var t,n,o,i,c,l,d='',a=(a=document.getElementsByTagName("script"))[a.length-1].getAttribute("data-injectcss");if(a&&!e.__iconfont__svg__cssinject__){e.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(e){console&&console.log(e)}}function s(){c||(c=!0,o())}t=function(){var e,t,n;(n=document.createElement("div")).innerHTML=d,d=null,(t=n.getElementsByTagName("svg")[0])&&(t.setAttribute("aria-hidden","true"),t.style.position="absolute",t.style.width=0,t.style.height=0,t.style.overflow="hidden",e=t,(n=document.body).firstChild?(t=n.firstChild).parentNode.insertBefore(e,t):n.appendChild(e))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(t,0):(n=function(){document.removeEventListener("DOMContentLoaded",n,!1),t()},document.addEventListener("DOMContentLoaded",n,!1)):document.attachEvent&&(o=t,i=e.document,c=!1,(l=function(){try{i.documentElement.doScroll("left")}catch(e){return void setTimeout(l,50)}s()})(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,s())})}(window);
--------------------------------------------------------------------------------
/src/assets/css/iconfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/inkmarkink/rainforest-blog-frontend/48dbec21f08f13e6b5657f158e58a2fdc82d34cf/src/assets/css/iconfont.ttf
--------------------------------------------------------------------------------
/src/assets/css/style.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --color-header-bg: #24292a;
3 | --color-text-white: #fff;
4 | --main-color: #fff;
5 | --assist-color: #0aa679;
6 | --accent-color: #e63657;
7 | --secondary-color: #50505c;
8 | --third-color: #808091;
9 | --border-color: #eaecef;
10 | --link-color: #0366d6;
11 | --text-font: Optima-Regular,Optima,-apple-system,system-ui,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,Helvetica Neue,PingFang SC,Hiragino Sans GB,Microsoft YaHei,Arial;
12 | }
--------------------------------------------------------------------------------
/src/components/breadcrumb/BBreadcrumb.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ item.meta.title }}
5 |
6 |
7 |
8 |
9 |
18 |
19 |
25 |
--------------------------------------------------------------------------------
/src/components/header/BHeader.vue:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
38 |
39 |
153 |
--------------------------------------------------------------------------------
/src/components/note/Note.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
19 |
20 |
21 |
22 |
27 |
28 |
81 |
--------------------------------------------------------------------------------
/src/components/notebook/Notebook.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
17 |
18 |
49 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import { createApp } from "vue";
2 | import App from "@/App.vue";
3 | import router from "@/router";
4 | import store from "@/store";
5 | import VueMarkdownEditor from "@/reliance/mdEditor.js";
6 | import VMdPreview from "@/reliance/mdPreview.js";
7 | import utils from "@/reliance/utils";
8 | import components from "@/reliance/elementPlus.js";
9 |
10 | const app = createApp(App);
11 | app.use(router);
12 | app.use(store);
13 | app.use(VueMarkdownEditor);
14 | app.use(VMdPreview);
15 | components.forEach((item) => {
16 | app.use(item);
17 | });
18 | app.config.globalProperties.$utils = utils;
19 | app.mount("#app");
20 |
--------------------------------------------------------------------------------
/src/reliance/elementPlus.js:
--------------------------------------------------------------------------------
1 | import {
2 | ElBacktop,
3 | ElButton,
4 | ElBreadcrumb,
5 | ElBreadcrumbItem,
6 | ElIcon,
7 | ElInput,
8 | ElMenu,
9 | ElMenuItem,
10 | ElOption,
11 | ElSelect,
12 | ElSubmenu,
13 | ElTable,
14 | ElTableColumn,
15 | ElDrawer,
16 | ElForm,
17 | ElFormItem,
18 | ElMessage,
19 | } from "element-plus";
20 | import "element-plus/lib/theme-chalk/index.css";
21 |
22 | const components = [
23 | ElBacktop,
24 | ElButton,
25 | ElBreadcrumb,
26 | ElBreadcrumbItem,
27 | ElDrawer,
28 | ElForm,
29 | ElFormItem,
30 | ElIcon,
31 | ElInput,
32 | ElMenu,
33 | ElMenuItem,
34 | ElMessage,
35 | ElOption,
36 | ElSelect,
37 | ElSubmenu,
38 | ElTable,
39 | ElTableColumn,
40 | ];
41 |
42 | export default components;
43 |
--------------------------------------------------------------------------------
/src/reliance/mdEditor.js:
--------------------------------------------------------------------------------
1 | import VueMarkdownEditor from "@kangc/v-md-editor";
2 | import "@kangc/v-md-editor/lib/style/base-editor.css";
3 | import githubTheme from "@kangc/v-md-editor/lib/theme/github.js";
4 | import "@kangc/v-md-editor/lib/theme/style/github.css";
5 | // import createMermaidPlugin from "@kangc/v-md-editor/lib/plugins/mermaid/cdn";
6 | import "@kangc/v-md-editor/lib/plugins/mermaid/mermaid.css";
7 |
8 | VueMarkdownEditor.use(githubTheme);
9 | // VueMarkdownEditor.use(createMermaidPlugin());
10 |
11 | export default VueMarkdownEditor;
12 |
--------------------------------------------------------------------------------
/src/reliance/mdPreview.js:
--------------------------------------------------------------------------------
1 | import VMdPreview from "@kangc/v-md-editor/lib/preview";
2 | import "@kangc/v-md-editor/lib/style/preview.css";
3 | import githubTheme from "@kangc/v-md-editor/lib/theme/github.js";
4 | import "@kangc/v-md-editor/lib/theme/style/github.css";
5 | import "@kangc/v-md-editor/lib/plugins/mermaid/mermaid.css";
6 | import createCopyCodePlugin from "@kangc/v-md-editor/lib/plugins/copy-code/index";
7 | import "@kangc/v-md-editor/lib/plugins/copy-code/copy-code.css";
8 | import createTodoListPlugin from "@kangc/v-md-editor/lib/plugins/todo-list/index";
9 | import "@kangc/v-md-editor/lib/plugins/todo-list/todo-list.css";
10 | import c from "highlight.js/lib/languages/c.js";
11 | import java from "highlight.js/lib/languages/java.js";
12 | import json from "highlight.js/lib/languages/json.js";
13 | import python from "highlight.js/lib/languages/python.js";
14 | import sql from "highlight.js/lib/languages/sql.js";
15 |
16 | VMdPreview.use(githubTheme, {
17 | extend(md, hljs) {
18 | // md为 markdown-it 实例,可以在此处进行修改配置,并使用 plugin 进行语法扩展
19 | // md.set(option).use(plugin);
20 | // 注册语言包
21 | hljs.registerLanguage("c", c);
22 | hljs.registerLanguage("json", json);
23 | hljs.registerLanguage("java", java);
24 | hljs.registerLanguage("python", python);
25 | hljs.registerLanguage("sql", sql);
26 | },
27 | });
28 | VMdPreview.use(createCopyCodePlugin());
29 | VMdPreview.use(createTodoListPlugin());
30 |
31 | export default VMdPreview;
32 |
--------------------------------------------------------------------------------
/src/reliance/utils.js:
--------------------------------------------------------------------------------
1 | import { htmlDecode, htmlDecodeObject } from "../utils/htmlUtils";
2 | import { getYearMonthDay, getMonthDay } from "../utils/timeUtils";
3 | import router from "../router/index";
4 |
5 | function changeRoute(path) {
6 | router.push({
7 | path: path,
8 | });
9 | }
10 |
11 | export default {
12 | htmlDecode,
13 | htmlDecodeObject,
14 | getYearMonthDay,
15 | getMonthDay,
16 | changeRoute,
17 | };
18 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import { createRouter, createWebHistory } from "vue-router";
2 | import store from "../store";
3 |
4 | const routes = [
5 | {
6 | path: "/",
7 | component: () => import("@/views/user/Home.vue"),
8 | redirect: "/overview",
9 | meta: {
10 | title: "Overview",
11 | },
12 | children: [
13 | {
14 | path: "/overview",
15 | component: () => import("@/views/user/overview/Overview.vue"),
16 | },
17 | {
18 | path: "/search",
19 | component: () => import("@/views/user/search/Search.vue"),
20 | },
21 | {
22 | path: "/nDetail/:id",
23 | component: () => import("@/views/user/nDetail/NDetail.vue"),
24 | meta: {
25 | title: "Notebook",
26 | },
27 | },
28 | {
29 | path: "/detail/:id",
30 | component: () => import("@/views/user/detail/Detail.vue"),
31 | meta: {
32 | title: "Note",
33 | },
34 | },
35 | {
36 | path: "/:pathMatch(.*)*",
37 | name: "NotFound",
38 | component: () => import("@/views/user/NotFound.vue"),
39 | },
40 | ],
41 | },
42 | {
43 | path: "/admin",
44 | name: "Home",
45 | component: () => import("@/views/admin/Home.vue"),
46 | meta: {
47 | title: "Admin",
48 | requireAuth: true,
49 | },
50 | redirect: "/admin/nList",
51 | children: [
52 | {
53 | path: "nList",
54 | name: "NList",
55 | component: () => import("@/views/admin/nList/NList.vue"),
56 | meta: {
57 | title: "NotebookList",
58 | },
59 | },
60 | {
61 | path: "list/:id",
62 | component: () => import("@/views/admin/list/List.vue"),
63 | meta: {
64 | title: "NoteList",
65 | },
66 | },
67 | {
68 | path: "detail/:pid/:id",
69 | component: () => import("@/views/admin/detail/Detail.vue"),
70 | meta: {
71 | title: "Detail",
72 | },
73 | },
74 | ],
75 | },
76 | {
77 | path: "/login",
78 | name: "Login",
79 | component: () => import("@/views/user/Login.vue"),
80 | },
81 | ];
82 |
83 | const router = createRouter({
84 | history: createWebHistory(process.env.BASE_URL),
85 | routes,
86 | });
87 |
88 | router.beforeEach((to) => {
89 | if (to.meta.requireAuth && store.getters.getLoginStatus === false) {
90 | return {
91 | path: "/login",
92 | };
93 | }
94 | });
95 |
96 | export default router;
97 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import { createStore } from "vuex";
2 |
3 | const store = createStore({
4 | state() {
5 | return {
6 | isLogin: false,
7 | };
8 | },
9 | mutations: {
10 | login(state) {
11 | state.isLogin = true;
12 | },
13 | logout(state) {
14 | state.isLogin = false;
15 | },
16 | },
17 | getters: {
18 | getLoginStatus(state) {
19 | return state.isLogin;
20 | },
21 | },
22 | });
23 |
24 | export default store;
25 |
--------------------------------------------------------------------------------
/src/utils/htmlUtils.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @param {String} str
3 | * @returns
4 | */
5 | export function htmlDecode(str) {
6 | if (str.length === 0) {
7 | return "";
8 | }
9 | return str
10 | .replace(/&/g, "&")
11 | .replace(/'/g, "'")
12 | .replace(/>/g, ">")
13 | .replace(/</g, "<")
14 | .replace(/"/g, '"')
15 | .replace(/ /g, " ");
16 | }
17 |
18 | /**
19 | * @param {Object} obj
20 | * @returns
21 | */
22 | export function htmlDecodeObject(obj) {
23 | if (obj === {}) {
24 | return {};
25 | }
26 | let newObj = obj;
27 | for (let key in newObj) {
28 | if (typeof newObj[key] === "string") {
29 | newObj[key] = htmlDecode(newObj[key]);
30 | }
31 | }
32 | return newObj;
33 | }
34 |
--------------------------------------------------------------------------------
/src/utils/timeUtils.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @param {Number} time
3 | * @returns
4 | */
5 | export function getYearMonthDay(time) {
6 | let date = new Date(time);
7 | let year = date.getFullYear();
8 | let month =
9 | date.getMonth() + 1 < 10
10 | ? "0" + (date.getMonth() + 1)
11 | : date.getMonth() + 1;
12 | let day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
13 | return year + "/" + month + "/" + day;
14 | }
15 |
16 | export function getMonthDay(time) {
17 | let date = new Date(time);
18 | let month =
19 | date.getMonth() + 1 < 10
20 | ? "0" + (date.getMonth() + 1)
21 | : date.getMonth() + 1;
22 | let day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
23 | return month + "/" + day;
24 | }
25 |
--------------------------------------------------------------------------------
/src/views/admin/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
24 |
38 |
--------------------------------------------------------------------------------
/src/views/admin/detail/Detail.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 标题
6 |
7 |
8 |
9 | 摘要
10 |
11 |
12 |
17 | 回到 List
18 |
19 | 提交
20 |
21 |
22 |
23 |
24 |
25 |
81 |
82 |
93 |
--------------------------------------------------------------------------------
/src/views/admin/list/List.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
15 |
16 |
17 |
18 |
27 | 查看
28 |
29 |
30 | 删除
31 |
32 |
33 |
34 |
35 |
36 |
37 |
40 |
41 |
42 |
43 |
73 |
74 |
85 |
--------------------------------------------------------------------------------
/src/views/admin/list/components/columns.js:
--------------------------------------------------------------------------------
1 | const columns = [
2 | {
3 | label: "标题",
4 | prop: "title",
5 | },
6 | {
7 | label: "摘要",
8 | prop: "abstract",
9 | },
10 | ];
11 |
12 | export default columns;
13 |
--------------------------------------------------------------------------------
/src/views/admin/nList/NList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
17 | 查看
18 |
19 |
20 | 编辑
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
33 |
40 | 取消
41 | 提交
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
120 |
121 |
138 |
--------------------------------------------------------------------------------
/src/views/admin/nList/components/columns.js:
--------------------------------------------------------------------------------
1 | const columns = [
2 | {
3 | label: "名字",
4 | prop: "name",
5 | },
6 | {
7 | label: "描述",
8 | prop: "description",
9 | },
10 | ];
11 |
12 | export default columns;
13 |
--------------------------------------------------------------------------------
/src/views/user/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
21 |
22 |
28 |
--------------------------------------------------------------------------------
/src/views/user/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |

10 |
11 |
31 |
32 |
33 |
47 |
48 |

51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
93 |
94 |
224 |
--------------------------------------------------------------------------------
/src/views/user/NotFound.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
30 |
31 |
57 |
--------------------------------------------------------------------------------
/src/views/user/detail/Detail.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
14 |
15 |
16 |
17 |
18 |
45 |
46 |
61 |
--------------------------------------------------------------------------------
/src/views/user/detail/components/ToolBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 浏览量
6 |
7 |
8 |
9 | 评论
10 |
11 |
12 |
13 | {{ $utils.getYearMonthDay(createdTime) }}
14 |
15 |
16 |
17 | {{ $utils.getYearMonthDay(updatedTime) }}
18 |
19 |
20 |
21 | go back
22 |
23 |
24 |
25 |
26 |
34 |
51 |
--------------------------------------------------------------------------------
/src/views/user/nDetail/NDetail.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
45 |
46 |
57 |
--------------------------------------------------------------------------------
/src/views/user/nDetail/components/NoteTable.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
13 |
14 |
15 | {{ item.title }}
16 |
17 |
18 | {{ $utils.getYearMonthDay(item.updated_time) }}
19 |
20 |
21 |
22 |
23 |
24 |
54 |
55 |
90 |
--------------------------------------------------------------------------------
/src/views/user/overview/Overview.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Brief Introduction
7 |
8 |
9 |
10 |
11 |
12 | Popular Notebooks
13 |
14 |
15 |
16 |
17 | Recent Notes
18 |
19 |
20 |
21 |
22 |
23 |
24 |
38 |
39 |
54 |
--------------------------------------------------------------------------------
/src/views/user/overview/components/List.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 | {{ item.title }}
11 |
12 |
13 | {{ item.abstract }}
14 |
15 |
16 | {{ $utils.getYearMonthDay(item.created_time) }}
17 |
18 |
19 | {{ $utils.getYearMonthDay(item.updated_time) }}
20 |
21 |
22 |
23 |
26 |
27 |
28 |
29 |
68 |
69 |
91 |
--------------------------------------------------------------------------------
/src/views/user/overview/components/NList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 | {{ item.name }}
10 |
11 |
12 | {{ item.description }}
13 |
14 |
15 |
16 |
17 |
18 |
42 |
43 |
51 |
--------------------------------------------------------------------------------
/src/views/user/overview/components/Profile.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |

7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
32 |
33 |
55 |
--------------------------------------------------------------------------------
/src/views/user/search/Search.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
11 |
12 |
13 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
30 |
31 | {{ item.name }}
32 |
33 |
34 | {{ item.description }}
35 |
36 |
37 |
38 |
39 |
40 |
41 |
88 |
89 |
105 |
--------------------------------------------------------------------------------
/src/views/user/search/components/options.js:
--------------------------------------------------------------------------------
1 | const options = [
2 | {
3 | value: "lastUpdate",
4 | label: "按时间排序",
5 | },
6 | {
7 | value: "name",
8 | label: "按标题排序",
9 | },
10 | ];
11 |
12 | export default options;
13 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | const compressionPlugin = require("compression-webpack-plugin");
2 |
3 | module.exports = {
4 | devServer: {
5 | port: 9000,
6 | proxy: {
7 | "/api": {
8 | target: "http://localhost:3000", // 你请求的第三方接口
9 | changeOrigin: true, // 在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
10 | pathRewrite: {
11 | // 路径重写,
12 | "^/api": "", // 替换target中的请求地址,也就是说 /api=/target,请求 /target 这个地址的时候直接写成 /api即可。
13 | },
14 | },
15 | },
16 | },
17 | // 修改 index.html 里面的 html-webpack-plugin 的值
18 | chainWebpack: (config) => {
19 | config.plugin("html").tap((args) => {
20 | args[0].title = "rainforest 的资料分享";
21 | return args;
22 | });
23 | },
24 | // 配置 gzip 压缩
25 | configureWebpack: () => {
26 | return {
27 | plugins: [
28 | new compressionPlugin({
29 | test: /\.js$|\.html$|\.css/,
30 | threshold: 10240,
31 | deleteOriginalAssets: false,
32 | }),
33 | ],
34 | };
35 | },
36 | productionSourceMap: true,
37 | };
38 |
--------------------------------------------------------------------------------