egg+vue+mongodb实践开发在线文档管理平台——水墨文档

发表于 3年以前  | 总阅读数:1103 次

前言

团队中会遇到在线文档管理的需求,包括技术文档,接口文档, excel 文档,和产品原型的托管等需求,一直没有找到合适的开源项目来满足需求,所以动手实现了个文档管理系统(实现起来并不复杂,该教程只是提供思路,并非最佳实践)

Github: https://github.com/huangwei9527/Ink-wash-docs

演示地址:http://www.inkwash.online/

功能列表

  • [x] 登录注册
  • [x] 工作台|文档列表
  • [x] 文档编辑预览(支持:md, excel,html产品原型托管)
  • [x] 协作编辑
  • [x] 访问权限设置
  • [x] 团队管理
  • [x] 点赞收藏
  • [x] 模板管理
  • [x] 浏览历史
  • [x] 回收站
  • [ ] 文件夹形式阅读(接口文档)
  • [ ] 编辑历史版本

系统界面预览

阅读前准备

1、了解 vue 技术栈开发 2、了解 koa3、了解 egg4、了解 mongodb

技术栈

前端:vue: 模块化开发少不了angular,react,vue三选一,这里选择了vue。vuex: 状态管理sass: css预编译器element-ui:不造轮子,有现成的优秀的vue组件库当然要用起来。

服务端:egg.js:企业级框架,按照一套统一的约定进行应用开发,开发十分高效。mongodb:一个基于分布式文件存储的数据库,比较灵活。egg-alinode:阿里提供的免费nodejs服务器性能监控。

工程搭建

这里我们将前后端项目放在同一个目录下管理,分别用 egg 脚手架和 vue-cli3 生成初始化项目,拷贝合并到同一个目录下,记得合并下 package.json 内容。(脚手架生成项目就不介绍了,按照文档来就是了),合并后将 vue 项目 src 目录改为 web ,如下:

···
·
|-- app                    // egg 初始化app目录
|-- config                // egg 初始化app目录
|-- public                // vue 静态资源目录
|-- web                    // 原 src 目录,改成 web 用作前端项目目录
·
···

这样的话 我们需要再把我们vue webpack打包配置稍作一下调整,首先是把原先的编译指向src的目录改成 web,其次为了 npm run build 能正常编译 web 我们也需要为 babel-loader 再增加一个编译目录

  • 根目录新增 vue.config.js ,目的是为了改造 vue 项目入口,改为: web/main.js

    module.exports = {    
      pages: {        
          index: {            
              entry: "web/main.js"        
          }    
      }
    }
  • babel-loader 能正常编译 web 目录, 在 vue.config.js 新增如下配置

// 扩展 webpack 配置
chainWebpack: config => {
    config.module
    .rule('js')
    .include.add(/web/).end()
    .use('babel')
    .loader('babel-loader')
    .tap(options => {
    // 修改它的选项...
    return options
    })
}
  • package.json 新增前端项目打包命令
"dev-web": "vue-cli-service serve",
"build-web": "vue-cli-service build",

至此前后端项目初始化工作就完了,前端开发启动npm run dev-web 后端开发启动 npm run dev

工程目录结构

|-- app                    --------服务器端项目代码
    |--controller                --------用于解析用户的输入,处理后返回相应的结果
    |--extend                    --------框架的扩展
    |--middleware                --------编写中间件
    |--model                    --------Schema数据模型
    |--public                    --------用于放置静态资源
    |--service                    --------用于编写业务逻辑层
    |--router.js                --------用于配置 URL 路由规则
|-- config                    --------egg 配置文件
    |--config.default.js            --------默认配置
    |--config.local.js                --------开发环境配置
    |--config.prod.js                --------生产环境配置
    |--plugin.js                    --------配置需要加载的插件
|-- web                        --------前端项目界面代码
    |--common                    --------前端界面对应静态资源
    |--components                --------组件
    |--config                    --------配置文件
    |--filter                    --------过滤器
    |--pages                    --------页面
    |--router                    --------路由配置
    |--store                    --------vuex状态管理
    |--service                    --------axios封装
    |--App.vue                    --------App
    |--main.js                    --------入口文件
    |--permission.js            --------权限控制
|-- docs                    --------预留编写项目文档目录
|-- vue.config.js            --------vue webpack配置文件
|-- package.json
...
...

完成项目目录初始化后,接下来先把 mongodb 全局得一些中间件、扩展方法给配置上,为接口开发做好准备工作

mongodb配置

1、安装 mongoose模块

npm install egg-mongoose --save

2、配置 config 文件

// config/plugin.js
exports.mongoose = {
    enable: true,
    package: 'egg-mongoose',
};

// config/config.default.js
config.mongoose = {
    url: 'mongodb://127.0.0.1:27017/inkwash',
    options: {},
};

全局中间件和扩展配置

1、统一处理接口

后端接口开发中我们需要一个统一得返回格式,可以在 context 对象下扩展个返回数据 function 用于统一处理接口 response data

app 下新建文件夹 extend 新建 context.js

// app/extend/context.js
module.exports = {
    /**
     * 返回客户端的内容
     * @param status // 接口是否成功
     * @param body // 返回数据
     * @param msg // 返回信息提示
     * @param code // 返回状态码
     */
    returnBody (status = true, body = {}, msg = 'success', code = 200) {
        this.status = code;
        this.body = {
            status: status,
            body: body,
            msg,
            code: code
        }
    }
}
// 调用
const { ctx } = this;
ctx.returnBody(true, {}, "成功");

2、添加统一处理错误得中间件

app文件夹下新建 middleware 文件夹,新建 error_handler.js , 并配置 congfig 全局中间件配置

// app/middleware/error_handler.js
module.exports = () => {

    return async function errorHandler(ctx, next) {
        try {
            await next();
        } catch (err) {
            // 所有的异常都会在app上出发一个error事件,框架会记录一条错误日志
            ctx.app.emit('error', err, ctx);

            const status = err.status || 500;

            // 如果时生产环境的时候 500错误的详细错误内容不返回给客户端
            const error = status === 500 && ctx.app.config.env === 'prod' ? '网络错误' : err.message;

            ctx.body = {
                msg: error,
                status: false,
                body: {},
                code: status
            };
        }
    };
};

// app/middleware/error_handler.js
// config/config.default.js 配置全局中间件
config.middleware = [ 'errorHandler'];

jwt鉴权登录认证

1、安装 egg-jwt token生成以及验证包

npm install egg-jwt --save

2、安装完成后在根目录下的 config/plugin.js 配置一下,如:

'use strict';

/** @type Egg.EggPlugin */
module.exports = {
    jwt: {
        enable: true,
        package: "egg-jwt"
    },
  mongoose: {
    enable: true,
    package: 'egg-mongoose',
  }
};

3、接下来在 config/config.default.js 里面继续配置:

config.jwt = {
  secret: "123456"//自定义 token 的加密条件字符串
};

4、在 context 上扩展两个 function , getTokencheckToken 用于生成 token 和验证 token

// app/extend/context.js
async getToken(data) {
    return await this.app.jwt.sign(data, this.app.config.jwt.secret, {expiresIn: 30* 24 * 60 * 60 + 's'});
},
async checkToken(token) {
    return await this.app.jwt.verify(token, this.app.config.jwt.secret)
}

5、编写个中间件实现登录验证拦截 在 app/middleware 文件夹下新建 auth.js

// app/middleware/auth.js
module.exports = () => {
    return async function(ctx, next) {
        let token = '';
        if (
            ctx.headers.authorization && ctx.headers.authorization.split(' ')[0] === 'Bearer'
        ) {
            token = ctx.headers.authorization.split(' ')[1];
        } else if (ctx.query.accesstoken) {
            token = ctx.query.accesstoken;
        } else if (ctx.request.body.accesstoken) {
            token = ctx.request.body.accesstoken;
        }
        let user;
        try{
            user = await ctx.checkToken(token);
        }catch (e) {
            ctx.returnBody(false,{}, 'Token 无效,请重新登录', 401);
        }
        if (!user) {
            ctx.returnBody(false,{}, 'Token 无效,请重新登录', 401);
            return;
        }
        ctx.request.user = user;
        await next();
    };
};

好了以上配置完成后就开始接下来的核心注册功能相关操作了。

  • 首先我在根目录下的 app/router.js 创建访问路由:
import { Application } from 'egg';

export default (app: Application) => {
  const { controller, router, jwt } = app;
  //正常路由
  router.post('/auth/register', controller.auth.register);

  // 只有在需要验证 token 的路由上添加jwt
  router.post('/user/infor',jwt, controller.user.infor); 
};
  • 接下来我去编写我的控制器,在根目录下的 app/controller/home.ts 编写内容:这里使用了两个我们在 app/extend/context.js 上扩展的两个通用方法
  1. 通过 ctx.getToken (用户信息 object 对象)将用户信息通过 jwt 生成 token 返回给前端
  2. 通过 ctx.returnBody 返回数据
// app/controller/auth.js
const Controller = require('egg').Controller
class AuthController extends Controller {
    async login() {
        //... 略
    }
    async register() {
        const { ctx, service } = this;
        const { username, password, email } = ctx.request.body
        let userData = await ctx.service.user.createUser(username, password, email);
        userData = userData.toObject();
        let userDataStr = JSON.parse(JSON.stringify(userData));
        // 生成token
        let token =await ctx.getToken(userDataStr);
        ctx.returnBody(true, {access_token: token, userInfo: userData}, "注册成功!")
    }
}

module.exports = AuthController;
  • 前端请求的时候需要在 headers 里面上默认的验证字断 Authorization 就可以了,如:
axios({
 method: 'get',
  url: 'http://127.0.0.1:7001/user/info',
  headers:{
      // 切记 token 不要直接发送,要在前面加上 Bearer 字符串和一个空格
    'Authorization':`Bearer ${token}`
  }
})
  • 接口从 token 获取加密信息

1.在 app/extend/context.js 再扩展个 getUser 方法获取 token 加密信息

// app/extend/context.js
// 获取用户信息
    async getUserData() {
        var token = this.headers.authorization ? this.headers.authorization : '';
        token = token.substring(7) //把Bearer 截取掉,解析的时候不需要加上Bearer
        let user = {}
        try {
            user = this.app.jwt.verify(token, this.app.config.jwt.secret);
        } catch (err) {
            user = {}
        }
        return user;
    }

2.实现获取个人信息接口

// app/controller/user.js
'use strict';

const Controller = require('egg').Controller;

class UserController extends Controller {
    async info() {
        let {ctx} = this;
        let user = await this.ctx.getUserData()
        ctx.returnBody(true, user)
    }
}

module.exports = UserController;

至此我们就实现了 jwt 生成 token , 然后通过前端传过来的 token 获取当前登录用户的信息, jwt 登录授权这块应该是讲完了,其他的业务接口应该实现起来难度不大

md文档编辑

文档编辑器使用 Vdito r, 一款浏览器端的 Markdown 编辑器,支持所见即所得(富文本)、即时渲染(类似 Typora )和分屏预览模式 安装 Vditor

npm install vditor --save

在代码中引入并初始化对象

<template>
  <div class="editor-component editor-md" ref="editor-component">
    <div id="editor-md-dom"></div>
  </div>
</template>

<script>
    import Vditor from 'vditor'
    import "vditor/src/assets/scss/index.scss"

    let timer = null;
    export default {
         data(){
             return {
                contentEditor: '',
            }
          },
          mounted () {
            this.contentEditor = new Vditor('vditor', {
              height: 360,
              toolbarConfig: {
                pin: true,
              },
              cache: {
                enable: false,
              },
              after: () => {
                this.contentEditor.setValue('hello, Vditor + Vue!')
              },
            })
         },
    }
</script>

excel表格编辑

安装 x-data-spreadsheet

npm install x-data-spreadsheet
<div id="x-spreadsheet-demo"></div>
import Spreadsheet from "x-data-spreadsheet";
// If you need to override the default options, you can set the override
// const options = {};
// new Spreadsheet('#x-spreadsheet-demo', options);
const s = new Spreadsheet("#x-spreadsheet-demo")
  .loadData({}) // load data
  .change(data => {
    // save data to db
  });

// data validation
s.validate()

axure原型托管

原型 axure 页面托管,参考 WuliHub 让用户上传生成的 html 压缩包,然后解压到静态资源目录,返回访问地址就 ok , 前端拿到原型地址用内嵌 iframe 渲染出来就 ok

打包编译&&静态资源设置

1、配置前端 vue 页面打包命令

// kage.json script新增打包命令
"build-web": "vue-cli-service build",

2、运行 npm run build-web 根目录会生成 dist 前端代码静态文件,因为 egg 支持设置多个静态资源目录,这里就直接配置根目录下的dist 文件夹为静态目录, 配置 config

// config/config.default.js
config.static = {
        prefix: '/',// 将静态资源前缀改为'/'(默认是 '/public')
        dir: [
            path.join(__dirname, '../app/public'), 
            path.join(__dirname, '../dist')
        ]
    }

打包完成后启动 egg , 就可以通过 http://localhost/:7001/index.html 访问到前端页面了


因为直接访问 http://localhost/:7001404可以再配置个路由重定向,将跟路由 '/' 重定向到 '/index.html'

// app/router.js 
// 重定向到index页面
app.router.redirect('/', '/index.html', 302);

部署

服务端部署运行 start 命令

npm run start

性能监控

node 服务性能监控这块可以使用阿里免费开源的 alinode1、安装 egg-alinode

npm i egg-alinode

2、插件配置

// config/plugin.js
exports.alinode = {
  enable: true,
  package: 'egg-alinode',
};

3、配置config

// config/config.default.js
exports.alinode = {
  enable: true,
  appid: 'my app id',
  secret: 'my app secret',
};

这样就可以了,监控数据可以在阿里 Node.js 性能平台控制台看到监控面板

本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/WmnJlCS36YKlfKJKo2D5nw

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 目录