2018-09-29

使用脚手架生成项目


cnpm i egg-init -g
egg-init  zhangximufengblog-api --type simple
cd zhangximufengblog-api
cnpm i

cnpm run dev
opoen localhost:7001

2. 编写用户注册功能 [#](#t12. 编写用户注册功能)

  • egg-mongoose

    2.1 使用egg-mongoose [#](#t22.1 使用egg-mongoose)

    3.1.1 安装 [#](#t33.1.1 安装)

    cnpm i egg-mongoose --save
    

3.1.2 启用插件 [#](#t43.1.2 启用插件)

// {app_root}config\plugin.js

exports.mongoose = {
    enable: true,
    package: 'egg-mongoose'
}

3.1.3 配置插件 [#](#t53.1.3 配置插件)

// {app_root}/config/config.default.js

exports.mongoose = {
  client: {
    url: 'mongodb://127.0.0.1/zhangximufengblog',
    options: {},
  },
};

2.2 配置模型 [#](#t62.2 配置模型)

// {app_root}/app/model/user.js

module.exports = app => {
    const mongoose = app.mongoose;
    const Schema = mongoose.Schema;
    const ObjectId = Schema.Types.ObjectId;
    const UserSchema = new Schema({
        username: { type: String, required: true },
        password: { type: String, required: true },
        email: String
    });
    return mongoose.model('User', UserSchema);
}

2.3 控制器中使用 [#](#t72.3 控制器中使用)

const BaseControler = require('./base');
class UserController extends BaseControler {
    //用户注册
    async signup() {
        let { ctx, app } = this;
        let user = ctx.request.body;
        try {
            user = await ctx.model.User.create(user);
            this.success(user);
        } catch (error) {
            this.error(error);
        }
    }
}

2.4 配置路由 [#](#t82.4 配置路由)

module.exports = app => {
  const { router, controller } = app;
  router.post('/api/users/signup', controller.users.signup);
};

2.5 暂时禁用CSRF [#](#t92.5 暂时禁用CSRF)

config\config.default.js

  config.security = {
    csrf: false
  }

3. 编写用户登录功能 [#](#t103. 编写用户登录功能)

3.1 控制器上增加方法 [#](#t113.1 控制器上增加方法)

    //用户登录
    async signin() {
        let { ctx, app } = this;
        let user = ctx.request.body;
        try {
            user = await ctx.model.User.findOne(user);
            if (user) {
                ctx.session.user = user;//保持会话
                this.success({ user });
            } else {
                this.error('用户名或密码错误');
            }
        } catch (error) {
            this.error(error);
        }
    }

3.2 配置路由 [#](#t123.2 配置路由)

 router.post('/api/users/signin', controller.users.signin);

4. 编写用户退出功能 [#](#t134. 编写用户退出功能)

4.1 控制器上增加方法 [#](#t144.1 控制器上增加方法)

async signout() {
        let { ctx } = this;
        ctx.session.user = null;
        this.success('success');
}

4.2 配置路由 [#](#t154.2 配置路由)

 router.get('/api/users/signout', controller.users.signout);

5. 分类管理 [#](#t165. 分类管理)

Method Path Controller.Action
POST /posts app.controllers.posts.create
GET /posts app.controllers.posts.index
PUT /posts/:id app.controllers.posts.update
DELETE /posts/:id app.controllers.posts.destroy

\app\router.js

router.resources('categories', '/api/categories', controller.categories);

app\model\category.js

module.exports = app => {
    const mongoose = app.mongoose;
    const Schema = mongoose.Schema;
    const ObjectId = Schema.Types.ObjectId;
    const CategorySchema = new Schema({
        name: { type: String, required: true }
    });
    return mongoose.model('Category', CategorySchema);
}

5.1 添加分类 [#](#t175.1 添加分类)

    async create() {
        let { ctx } = this;
        let category = ctx.request.body;
        try {
            let doc = await ctx.model.Category.create(category);
            this.success('success');
        } catch (err) {
            this.error(error);
        }
    }

5.2 查看分类列表 [#](#t185.2 查看分类列表)

 //查询分类列表
    async index() {
        let { ctx } = this;
        let { pageNum = 1, pageSize = 10, keyword } = ctx.query;
        pageNum = isNaN(pageNum) ? 1 : parseInt(pageNum);
        pageSize = isNaN(pageSize) ? 1 : parseInt(pageSize);
        let query = {};
        if (keyword) {
            query.name = new RegExp(keyword);
        }
        let total = await ctx.model.Category.count(query);
        let items = await ctx.model.Category.find(query).skip((pageNum - 1) * pageSize).limit(pageSize);
        this.success({
            items,
            pageNum,
            pageSize,
            total,
            pageCount: Math.ceil(total / pageSize)
        });
    }

5.3 修改分类 [#](#t195.3 修改分类)

 //修改分类
    async update() {
        let { ctx } = this;
        let id = ctx.params.id;
        let category = ctx.request.body;
        try {
            let result = await ctx.model.Category.findByIdAndUpdate(id, category);
            this.success('success');
        } catch (err) {
            this.error(error);
        }
    }

5.4 删除分类 [#](#t205.4 删除分类)

 //删除分类
    async destroy() {
        let { ctx } = this;
        let id = ctx.params.id;
        let { ids = [] } = ctx.request.body;
        ids.push(id);
        try {
            await ctx.model.Category.remove({ _id: { $in: ids } });
            this.success('success');
        } catch (error) {
            this.error(error);
        }
    }

6. 文章管理 [#](#t216. 文章管理)

\app\router.js

router.resources('articles', '/api/articles', controller.articles);
router.get('/api/articles/pv/:id', controller.articles.updatePv);
router.post('/api/articles/comment/:id', controller.articles.comment);

app\model\article.js

module.exports=app => {
    const mongoose=app.mongoose;
    const Schema=mongoose.Schema;
    const ObjectId=Schema.Types.ObjectId;
    const ArticleSchema=new Schema({
        user: {type: ObjectId,ref: 'User'},
        category: { type: ObjectId, ref: 'Category' },
        title: String,
        content: String,
        pv: { type: Number, default: 0 },
        comments: [{ user: { type: ObjectId, ref: 'User' }, content: String, createAt: { type: Date, default: Date.now } }],
        createAt: { type: Date, default: Date.now }
    });
    return mongoose.model('Article',ArticleSchema);
}

6.1 添加文章 [#](#t226.1 添加文章)

  async create() {
    let { ctx } = this;
    let article = ctx.request.body;
    article.user = this.user._id;
    try {
      let doc = await ctx.model.Article.create(article);
      this.success('success');
    } catch (error) {
      this.error(error);
    }
  }

6.2 查看文章列表 [#](#t236.2 查看文章列表)

async index() {
    let { ctx } = this;
    let { pageNum = 1, pageSize = 10, keyword } = ctx.query;
    pageNum = isNaN(pageNum) ? 1 : parseInt(pageNum);
    pageSize = isNaN(pageSize) ? 1 : parseInt(pageSize);
    let query = {};
    if (keyword) {
      query.title = new RegExp(keyword);
    }
    let total = await ctx.model.Article.count(query);
    let items = await ctx.model.Article.find(query).populate('category').populate('comments').skip((pageNum - 1) * pageSize).limit(pageSize);
    this.success({
      items,
      pageNum,
      pageSize,
      total,
      pageCount: Math.ceil(total / pageSize)
    });
  }

6.3 修改文章 [#](#t246.3 修改文章)

 async update() {
    let { ctx } = this;
    let id = ctx.params.id;
    let article = ctx.request.body;
    try {
      let result = await ctx.model.Article.findByIdAndUpdate(id, article);
      this.success('success');
    } catch (err) {
      this.error(error);
    }
  }

6.4 删除文章 [#](#t256.4 删除文章)

  async destroy() {
    let { ctx } = this;
    let { ids } = ctx.request.body;
    try {
      await ctx.model.Article.remove({ _id: { $in: ids } });
      this.success('success');
    } catch (error) {
      this.error(error);
    }
  }

6.5 修改阅读量 [#](#t266.5 修改阅读量)

  async updatePv() {
    let { ctx } = this;
    let id = ctx.params.id;
    try {
      let result = await ctx.model.Article.findByIdAndUpdate(id, { $inc: { pv: 1 } });
      this.success('success');
    } catch (error) {
      this.error(error);
    }
  }

6.6 评论文章 [#](#t276.6 评论文章)

  async comment() {
    let { ctx } = this;
    let id = ctx.params.id;
    let comment = ctx.request.body;
    comment.user = this.user._id;;
    try {
      let result = await ctx.model.Article.findByIdAndUpdate(id, { $push: { comments: comment } });
      this.success('success');
    } catch (err) {
      this.error(error);
    }
  }

7. 处理跨域 [#](#t287. 处理跨域)

npm i egg-cors --save
    // {app_root}/config/plugin.js
    exports.cors = {
    enable: true,
    package: 'egg-cors',
    };
//{app_root}/config/config.default.js

    exports.security = {
    domainWhiteList: [ 'http://localhost:4200' ],
    };

8. 会话持久化 [#](#t298. 会话持久化)

// {app_root}/config/plugin.js

exports.sessionRedis = {
  enable: true,
  package: 'egg-session-redis',
};

exports.redis = {
  enable: true,
  package: 'egg-redis',
}

// {app_root}/config/config.default.js

exports.redis = {
  client: {
    host: '127.0.0.1',
    port: '6379',
    password: 'zxmf',
    db: '0',
  },
  agent:true
};

9. 开发 [#](#t309. 开发)

9.1 指定运行环境 [#](#t319.1 指定运行环境)

EGG_SERVER_ENV=prod
app.config.env
config
|- config.default.js
|- config.test.js
|- config.prod.js
|- config.unittest.js
`- config.local.js

附录 #

Gitalking ...

Markdown is supported

Be the first guy leaving a comment!