asd123a20 3 年之前
當前提交
feffc3bc55
共有 100 個文件被更改,包括 3137 次插入0 次删除
  1. 29 0
      service-cms/.autod.conf.js
  2. 1 0
      service-cms/.eslintignore
  3. 3 0
      service-cms/.eslintrc
  4. 46 0
      service-cms/.github/workflows/nodejs.yml
  5. 14 0
      service-cms/.gitignore
  6. 12 0
      service-cms/.travis.yml
  7. 33 0
      service-cms/README.md
  8. 23 0
      service-cms/app/controller/column.js
  9. 27 0
      service-cms/app/controller/content.js
  10. 27 0
      service-cms/app/controller/imgnews.js
  11. 23 0
      service-cms/app/controller/imgtype.js
  12. 23 0
      service-cms/app/controller/menu.js
  13. 27 0
      service-cms/app/controller/pages.js
  14. 23 0
      service-cms/app/controller/toconfig.js
  15. 11 0
      service-cms/app/model/column.js
  16. 31 0
      service-cms/app/model/content.js
  17. 27 0
      service-cms/app/model/imgnews.js
  18. 11 0
      service-cms/app/model/imgtype.js
  19. 23 0
      service-cms/app/model/menu.js
  20. 23 0
      service-cms/app/model/pages.js
  21. 13 0
      service-cms/app/model/toconfig.js
  22. 46 0
      service-cms/app/router.js
  23. 77 0
      service-cms/app/service/column.js
  24. 81 0
      service-cms/app/service/content.js
  25. 81 0
      service-cms/app/service/imgnews.js
  26. 67 0
      service-cms/app/service/imgtype.js
  27. 73 0
      service-cms/app/service/menu.js
  28. 89 0
      service-cms/app/service/pages.js
  29. 67 0
      service-cms/app/service/toconfig.js
  30. 14 0
      service-cms/appveyor.yml
  31. 52 0
      service-cms/config/config.default.js
  32. 9 0
      service-cms/config/plugin.js
  33. 17 0
      service-cms/ecosystem.config.js
  34. 5 0
      service-cms/jsconfig.json
  35. 48 0
      service-cms/package.json
  36. 9 0
      service-cms/server.js
  37. 20 0
      service-cms/test/app/controller/home.test.js
  38. 29 0
      service-code/.autod.conf.js
  39. 1 0
      service-code/.eslintignore
  40. 3 0
      service-code/.eslintrc
  41. 46 0
      service-code/.github/workflows/nodejs.yml
  42. 14 0
      service-code/.gitignore
  43. 12 0
      service-code/.travis.yml
  44. 33 0
      service-code/README.md
  45. 23 0
      service-code/app/controller/dictionary.js
  46. 24 0
      service-code/app/controller/type.js
  47. 12 0
      service-code/app/model/dictionary.js
  48. 11 0
      service-code/app/model/type.js
  49. 18 0
      service-code/app/router.js
  50. 65 0
      service-code/app/service/dictionary.js
  51. 65 0
      service-code/app/service/type.js
  52. 14 0
      service-code/appveyor.yml
  53. 54 0
      service-code/config/config.default.js
  54. 9 0
      service-code/config/plugin.js
  55. 17 0
      service-code/ecosystem.config.js
  56. 5 0
      service-code/jsconfig.json
  57. 47 0
      service-code/package.json
  58. 9 0
      service-code/server.js
  59. 20 0
      service-code/test/app/controller/home.test.js
  60. 29 0
      service-files/.autod.conf.js
  61. 1 0
      service-files/.eslintignore
  62. 3 0
      service-files/.eslintrc
  63. 14 0
      service-files/.gitignore
  64. 12 0
      service-files/.travis.yml
  65. 33 0
      service-files/README.md
  66. 19 0
      service-files/app/controller/filestore.js
  67. 12 0
      service-files/app/model/filestore.js
  68. 11 0
      service-files/app/router.js
  69. 84 0
      service-files/app/service/filestore.js
  70. 14 0
      service-files/appveyor.yml
  71. 67 0
      service-files/config/config.default.js
  72. 9 0
      service-files/config/plugin.js
  73. 17 0
      service-files/ecosystem.config.js
  74. 5 0
      service-files/jsconfig.json
  75. 50 0
      service-files/package.json
  76. 9 0
      service-files/server.js
  77. 20 0
      service-files/test/app/controller/home.test.js
  78. 29 0
      service-gateway/.autod.conf.js
  79. 1 0
      service-gateway/.eslintignore
  80. 3 0
      service-gateway/.eslintrc
  81. 46 0
      service-gateway/.github/workflows/nodejs.yml
  82. 14 0
      service-gateway/.gitignore
  83. 12 0
      service-gateway/.travis.yml
  84. 33 0
      service-gateway/README.md
  85. 142 0
      service-gateway/app/controller/home.js
  86. 12 0
      service-gateway/app/router.js
  87. 14 0
      service-gateway/appveyor.yml
  88. 197 0
      service-gateway/config/cms.js
  89. 54 0
      service-gateway/config/code.js
  90. 60 0
      service-gateway/config/config.default.js
  91. 22 0
      service-gateway/config/files.js
  92. 34 0
      service-gateway/config/log.js
  93. 46 0
      service-gateway/config/login.js
  94. 147 0
      service-gateway/config/naf.js
  95. 9 0
      service-gateway/config/plugin.js
  96. 48 0
      service-gateway/config/wx.js
  97. 17 0
      service-gateway/ecosystem.config.js
  98. 5 0
      service-gateway/jsconfig.json
  99. 47 0
      service-gateway/package.json
  100. 0 0
      service-gateway/server.js

+ 29 - 0
service-cms/.autod.conf.js

@@ -0,0 +1,29 @@
+'use strict';
+
+module.exports = {
+  write: true,
+  prefix: '^',
+  plugin: 'autod-egg',
+  test: [
+    'test',
+    'benchmark',
+  ],
+  dep: [
+    'egg',
+    'egg-scripts',
+  ],
+  devdep: [
+    'egg-ci',
+    'egg-bin',
+    'egg-mock',
+    'autod',
+    'autod-egg',
+    'eslint',
+    'eslint-config-egg',
+  ],
+  exclude: [
+    './test/fixtures',
+    './dist',
+  ],
+};
+

+ 1 - 0
service-cms/.eslintignore

@@ -0,0 +1 @@
+coverage

+ 3 - 0
service-cms/.eslintrc

@@ -0,0 +1,3 @@
+{
+  "extends": "eslint-config-egg"
+}

+ 46 - 0
service-cms/.github/workflows/nodejs.yml

@@ -0,0 +1,46 @@
+# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
+# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
+
+name: Node.js CI
+
+on:
+  push:
+    branches:
+      - main
+      - master
+  pull_request:
+    branches:
+      - main
+      - master
+  schedule:
+    - cron: '0 2 * * *'
+
+jobs:
+  build:
+    runs-on: ${{ matrix.os }}
+
+    strategy:
+      fail-fast: false
+      matrix:
+        node-version: [10]
+        os: [ubuntu-latest, windows-latest, macos-latest]
+
+    steps:
+    - name: Checkout Git Source
+      uses: actions/checkout@v2
+
+    - name: Use Node.js ${{ matrix.node-version }}
+      uses: actions/setup-node@v1
+      with:
+        node-version: ${{ matrix.node-version }}
+
+    - name: Install Dependencies
+      run: npm i -g npminstall && npminstall
+
+    - name: Continuous Integration
+      run: npm run ci
+
+    - name: Code Coverage
+      uses: codecov/codecov-action@v1
+      with:
+        token: ${{ secrets.CODECOV_TOKEN }}

+ 14 - 0
service-cms/.gitignore

@@ -0,0 +1,14 @@
+logs/
+npm-debug.log
+yarn-error.log
+node_modules/
+package-lock.json
+yarn.lock
+coverage/
+.idea/
+run/
+.DS_Store
+*.sw*
+*.un~
+typings/
+.nyc_output/

+ 12 - 0
service-cms/.travis.yml

@@ -0,0 +1,12 @@
+
+language: node_js
+node_js:
+  - '10'
+before_install:
+  - npm i npminstall -g
+install:
+  - npminstall
+script:
+  - npm run ci
+after_script:
+  - npminstall codecov && codecov

+ 33 - 0
service-cms/README.md

@@ -0,0 +1,33 @@
+# service-cms
+
+
+
+## QuickStart
+
+<!-- add docs here for user -->
+
+see [egg docs][egg] for more detail.
+
+### Development
+
+```bash
+$ npm i
+$ npm run dev
+$ open http://localhost:7001/
+```
+
+### Deploy
+
+```bash
+$ npm start
+$ npm stop
+```
+
+### npm scripts
+
+- Use `npm run lint` to check code style.
+- Use `npm test` to run unit test.
+- Use `npm run autod` to auto detect dependencies upgrade, see [autod](https://www.npmjs.com/package/autod) for more detail.
+
+
+[egg]: https://eggjs.org

+ 23 - 0
service-cms/app/controller/column.js

@@ -0,0 +1,23 @@
+'use strict';
+const Controller = require('egg').Controller;
+
+class ColumnController extends Controller {
+  async create() {
+    const res = await this.ctx.service.column.create(this.ctx.request.body);
+    this.ctx.body = res;
+  }
+  async update() {
+    const res = await this.ctx.service.column.update(this.ctx.request.body);
+    this.ctx.body = res;
+  }
+  async delete() {
+    const res = await this.ctx.service.column.delete(this.ctx.params);
+    this.ctx.body = res;
+  }
+  async query() {
+    const res = await this.ctx.service.column.query(this.ctx.query);
+    this.ctx.body = res;
+  }
+}
+
+module.exports = ColumnController;

+ 27 - 0
service-cms/app/controller/content.js

@@ -0,0 +1,27 @@
+'use strict';
+const Controller = require('egg').Controller;
+
+class ContentController extends Controller {
+  async create() {
+    const res = await this.ctx.service.content.create(this.ctx.request.body);
+    this.ctx.body = res;
+  }
+  async update() {
+    const res = await this.ctx.service.content.update(this.ctx.request.body);
+    this.ctx.body = res;
+  }
+  async delete() {
+    const res = await this.ctx.service.content.delete(this.ctx.params);
+    this.ctx.body = res;
+  }
+  async query() {
+    const res = await this.ctx.service.content.query(this.ctx.query);
+    this.ctx.body = res;
+  }
+  async fetch() {
+    const res = await this.ctx.service.content.fetch(this.ctx.query);
+    this.ctx.body = res;
+  }
+}
+
+module.exports = ContentController;

+ 27 - 0
service-cms/app/controller/imgnews.js

@@ -0,0 +1,27 @@
+'use strict';
+const Controller = require('egg').Controller;
+
+class ImgnewsController extends Controller {
+  async create() {
+    const res = await this.ctx.service.imgnews.create(this.ctx.request.body);
+    this.ctx.body = res;
+  }
+  async update() {
+    const res = await this.ctx.service.imgnews.update(this.ctx.request.body);
+    this.ctx.body = res;
+  }
+  async delete() {
+    const res = await this.ctx.service.imgnews.delete(this.ctx.params);
+    this.ctx.body = res;
+  }
+  async query() {
+    const res = await this.ctx.service.imgnews.query(this.ctx.query);
+    this.ctx.body = res;
+  }
+  async fetch() {
+    const res = await this.ctx.service.imgnews.fetch(this.ctx.query);
+    this.ctx.body = res;
+  }
+}
+
+module.exports = ImgnewsController;

+ 23 - 0
service-cms/app/controller/imgtype.js

@@ -0,0 +1,23 @@
+'use strict';
+const Controller = require('egg').Controller;
+
+class ImgtypeController extends Controller {
+  async create() {
+    const res = await this.ctx.service.imgtype.create(this.ctx.request.body);
+    this.ctx.body = res;
+  }
+  async update() {
+    const res = await this.ctx.service.imgtype.update(this.ctx.request.body);
+    this.ctx.body = res;
+  }
+  async delete() {
+    const res = await this.ctx.service.imgtype.delete(this.ctx.params);
+    this.ctx.body = res;
+  }
+  async query() {
+    const res = await this.ctx.service.imgtype.query(this.ctx.query);
+    this.ctx.body = res;
+  }
+}
+
+module.exports = ImgtypeController;

+ 23 - 0
service-cms/app/controller/menu.js

@@ -0,0 +1,23 @@
+'use strict';
+const Controller = require('egg').Controller;
+
+class MenuController extends Controller {
+  async create() {
+    const res = await this.ctx.service.menu.create(this.ctx.request.body);
+    this.ctx.body = res;
+  }
+  async update() {
+    const res = await this.ctx.service.menu.update(this.ctx.request.body);
+    this.ctx.body = res;
+  }
+  async delete() {
+    const res = await this.ctx.service.menu.delete(this.ctx.params);
+    this.ctx.body = res;
+  }
+  async query() {
+    const res = await this.ctx.service.menu.query(this.ctx.query);
+    this.ctx.body = res;
+  }
+}
+
+module.exports = MenuController;

+ 27 - 0
service-cms/app/controller/pages.js

@@ -0,0 +1,27 @@
+'use strict';
+const Controller = require('egg').Controller;
+
+class PagesController extends Controller {
+  async create() {
+    const res = await this.ctx.service.pages.create(this.ctx.request.body);
+    this.ctx.body = res;
+  }
+  async update() {
+    const res = await this.ctx.service.pages.update(this.ctx.request.body);
+    this.ctx.body = res;
+  }
+  async delete() {
+    const res = await this.ctx.service.pages.delete(this.ctx.params);
+    this.ctx.body = res;
+  }
+  async query() {
+    const res = await this.ctx.service.pages.query(this.ctx.query);
+    this.ctx.body = res;
+  }
+  async fetch() {
+    const res = await this.ctx.service.pages.fetch(this.ctx.query);
+    this.ctx.body = res;
+  }
+}
+
+module.exports = PagesController;

+ 23 - 0
service-cms/app/controller/toconfig.js

@@ -0,0 +1,23 @@
+'use strict';
+const Controller = require('egg').Controller;
+
+class ToconfigController extends Controller {
+  async create() {
+    const res = await this.ctx.service.toconfig.create(this.ctx.request.body);
+    this.ctx.body = res;
+  }
+  async update() {
+    const res = await this.ctx.service.toconfig.update(this.ctx.request.body);
+    this.ctx.body = res;
+  }
+  async delete() {
+    const res = await this.ctx.service.toconfig.delete(this.ctx.params);
+    this.ctx.body = res;
+  }
+  async query() {
+    const res = await this.ctx.service.toconfig.query(this.ctx.query);
+    this.ctx.body = res;
+  }
+}
+
+module.exports = ToconfigController;

+ 11 - 0
service-cms/app/model/column.js

@@ -0,0 +1,11 @@
+'use strict';
+const Schema = require('mongoose').Schema;
+const SchemaDefine = {
+  code: { type: String, required: true },
+  name: { type: String, required: true },
+};
+const schema = new Schema(SchemaDefine);
+module.exports = app => {
+  const { mongoose } = app;
+  return mongoose.model('column', schema, 'column');
+};

+ 31 - 0
service-cms/app/model/content.js

@@ -0,0 +1,31 @@
+'use strict';
+const Schema = require('mongoose').Schema;
+const SchemaDefine = {
+  // 置顶
+  istop: { type: Boolean, required: false, default: false },
+  // 排序
+  date: { type: String, required: false },
+  // 添加时间
+  createAt: { type: Number, required: true },
+  // 修改时间
+  updateAt: { type: Number, required: true },
+  // 缩略图
+  thumbnail: { type: String, required: false },
+  // 标题
+  title: { type: String, required: true },
+  // 描述
+  describe: { type: String, required: true },
+  // 内容
+  content: { type: String, required: true },
+  // 绑定栏目
+  bind: { type: String, required: true },
+  // 访问量
+  visit: { type: Number, required: false, default: 0 },
+  // 推荐
+  recommend: { type: Boolean, required: false, default: false },
+};
+const schema = new Schema(SchemaDefine);
+module.exports = app => {
+  const { mongoose } = app;
+  return mongoose.model('content', schema, 'content');
+};

+ 27 - 0
service-cms/app/model/imgnews.js

@@ -0,0 +1,27 @@
+'use strict';
+const Schema = require('mongoose').Schema;
+const SchemaDefine = {
+  // 排序
+  date: { type: Number, required: false, default: 0 },
+  // 添加时间
+  createAt: { type: Number, required: true },
+  // 修改时间
+  updateAt: { type: Number, required: true },
+  // 图片
+  img: { type: String, required: true },
+  // 绑定类型
+  bind: { type: String, required: true },
+  // 类型
+  type: { type: Number, required: true }, // 0 = 栏目  1 = 单页  2 = 链接
+  // 链接地址
+  url: { type: String, required: false },
+  // 绑定栏目
+  column: { type: String, required: false },
+  // 绑定单页
+  pages: { type: String, required: false },
+};
+const schema = new Schema(SchemaDefine);
+module.exports = app => {
+  const { mongoose } = app;
+  return mongoose.model('imgnews', schema, 'imgnews');
+};

+ 11 - 0
service-cms/app/model/imgtype.js

@@ -0,0 +1,11 @@
+'use strict';
+const Schema = require('mongoose').Schema;
+const SchemaDefine = {
+  code: { type: String, required: true },
+  name: { type: String, required: true },
+};
+const schema = new Schema(SchemaDefine);
+module.exports = app => {
+  const { mongoose } = app;
+  return mongoose.model('imgtype', schema, 'imgtype');
+};

+ 23 - 0
service-cms/app/model/menu.js

@@ -0,0 +1,23 @@
+'use strict';
+const Schema = require('mongoose').Schema;
+const SchemaDefine = {
+  // 排序
+  date: { type: Number, required: false },
+  // 编码
+  code: { type: String, required: true },
+  // 名称
+  name: { type: String, required: true },
+  // 类型
+  type: { type: String, required: true }, // 0 = 栏目  1 = 单页  2 = 链接
+  // 链接地址
+  url: { type: String, required: false },
+  // 绑定栏目
+  column: { type: String, required: false },
+  // 绑定单页
+  pages: { type: String, required: false },
+};
+const schema = new Schema(SchemaDefine);
+module.exports = app => {
+  const { mongoose } = app;
+  return mongoose.model('menu', schema, 'menu');
+};

+ 23 - 0
service-cms/app/model/pages.js

@@ -0,0 +1,23 @@
+'use strict';
+const Schema = require('mongoose').Schema;
+const SchemaDefine = {
+  // 添加时间
+  createAt: { type: Number, required: true },
+  // 修改时间
+  updateAt: { type: Number, required: true },
+  // 编码
+  code: { type: String, required: true },
+  // 标题
+  title: { type: String, required: true },
+  // 描述
+  describe: { type: String, required: true },
+  // 内容
+  content: { type: String, required: true },
+  // 访问量
+  visit: { type: Number, required: false, default: 0 },
+};
+const schema = new Schema(SchemaDefine);
+module.exports = app => {
+  const { mongoose } = app;
+  return mongoose.model('pages', schema, 'pages');
+};

+ 13 - 0
service-cms/app/model/toconfig.js

@@ -0,0 +1,13 @@
+'use strict';
+const Schema = require('mongoose').Schema;
+const SchemaDefine = {
+  code: { type: String, required: true },
+  name: { type: String, required: true },
+  value: { type: String, required: true },
+  type: { type: String, required: true },
+};
+const schema = new Schema(SchemaDefine);
+module.exports = app => {
+  const { mongoose } = app;
+  return mongoose.model('toconfig', schema, 'toconfig');
+};

+ 46 - 0
service-cms/app/router.js

@@ -0,0 +1,46 @@
+'use strict';
+
+/**
+ * @param {Egg.Application} app - egg application
+ */
+module.exports = app => {
+  const { router, controller } = app;
+  // 栏目
+  router.post('/api/cms/column/create', controller.column.create);
+  router.post('/api/cms/column/update', controller.column.update);
+  router.delete('/api/cms/column/delete/:id', controller.column.delete);
+  router.get('/api/cms/column/query', controller.column.query);
+  // 内容
+  router.post('/api/cms/contents/create', controller.content.create);
+  router.post('/api/cms/contents/update', controller.content.update);
+  router.delete('/api/cms/contents/delete/:id', controller.content.delete);
+  router.get('/api/cms/contents/query', controller.content.query);
+  router.get('/api/cms/contents/fetch', controller.content.fetch);
+  // 图片新闻类型
+  router.post('/api/cms/imgtype/create', controller.imgtype.create);
+  router.post('/api/cms/imgtype/update', controller.imgtype.update);
+  router.delete('/api/cms/imgtype/delete/:id', controller.imgtype.delete);
+  router.get('/api/cms/imgtype/query', controller.imgtype.query);
+  // 图片新闻
+  router.post('/api/cms/imgnews/create', controller.imgnews.create);
+  router.post('/api/cms/imgnews/update', controller.imgnews.update);
+  router.delete('/api/cms/imgnews/delete/:id', controller.imgnews.delete);
+  router.get('/api/cms/imgnews/query', controller.imgnews.query);
+  router.get('/api/cms/imgnews/fetch', controller.imgnews.fetch);
+  // 菜单
+  router.post('/api/cms/menus/create', controller.menu.create);
+  router.post('/api/cms/menus/update', controller.menu.update);
+  router.delete('/api/cms/menus/delete/:id', controller.menu.delete);
+  router.get('/api/cms/menus/query', controller.menu.query);
+  // 单页
+  router.post('/api/cms/pages/create', controller.pages.create);
+  router.post('/api/cms/pages/update', controller.pages.update);
+  router.delete('/api/cms/pages/delete/:id', controller.pages.delete);
+  router.get('/api/cms/pages/query', controller.pages.query);
+  router.get('/api/cms/pages/fetch', controller.pages.fetch);
+  // 配置
+  router.post('/api/cms/toconfig/create', controller.toconfig.create);
+  router.post('/api/cms/toconfig/update', controller.toconfig.update);
+  router.delete('/api/cms/toconfig/delete/:id', controller.toconfig.delete);
+  router.get('/api/cms/toconfig/query', controller.toconfig.query);
+};

+ 77 - 0
service-cms/app/service/column.js

@@ -0,0 +1,77 @@
+'use strict';
+
+const assert = require('assert');
+const Service = require('egg').Service;
+class ColumnService extends Service {
+  constructor(ctx) {
+    super(ctx);
+    this.model = this.ctx.model.Column;
+    this.content = this.ctx.model.Content;
+    this.menu = this.ctx.model.Menu;
+    this.imgnews = this.ctx.model.Imgnews;
+  }
+  async create({ name, code }) {
+    assert(name, '名称不存在');
+    assert(code, '编码不存在');
+    try {
+      const res = await this.model.findOne({ code });
+      if (res) return { errcode: -1001, errmsg: '编码已存在', data: '' };
+      const item = await this.model.create({ name, code });
+      return { errcode: 0, errmsg: '', data: item };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async update({ id, name }) {
+    assert(id, 'id不存在');
+    try {
+      const res = await this.model.findOne({ _id: id });
+      if (!res) return { errcode: -1001, errmsg: '数据不存在', data: '' };
+      await this.model.updateOne({ _id: id }, { name });
+      return { errcode: 0, errmsg: '', data: 'update' };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async delete({ id }) {
+    assert(id, 'id不存在');
+    try {
+      const res = await this.model.findOne({ _id: id });
+      if (!res) return { errcode: -1001, errmsg: '数据不存在', data: '' };
+      const content = await this.content.findOne({ bind: res.code });
+      const menu = await this.menu.findOne({ column: res.code });
+      const imgnews = await this.imgnews.findOne({ column: res.code });
+      if (content || menu || imgnews) {
+        let errmsg = '';
+        if (content) errmsg += '(内容)';
+        if (menu) errmsg += '(菜单)';
+        if (imgnews) errmsg += '(图片新闻)';
+        return { errcode: -1001, errmsg: `存在${errmsg}绑定关系,不能删除`, data: '' };
+      }
+      await this.model.remove({ _id: id });
+      return { errcode: 0, errmsg: '', data: 'delete' };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async query({ skip, limit, code, name }) {
+    const filter = {};
+    if (name || code) filter.$or = [];
+    if (code) filter.$or.push({ code: { $regex: code } });
+    if (name) filter.$or.push({ name: { $regex: name } });
+    try {
+      let res;
+      const total = await this.model.find({ ...filter });
+      if (skip && limit) {
+        res = await this.model.find({ ...filter }).skip(Number(skip) * Number(limit)).limit(Number(limit));
+      } else {
+        res = await this.model.find({ ...filter });
+      }
+      return { errcode: 0, errmsg: '', data: res, total: total.length };
+    } catch (error) {
+      throw error;
+    }
+  }
+}
+
+module.exports = ColumnService;

+ 81 - 0
service-cms/app/service/content.js

@@ -0,0 +1,81 @@
+'use strict';
+
+const assert = require('assert');
+const moment = require('moment');
+const Service = require('egg').Service;
+class ContentService extends Service {
+  constructor(ctx) {
+    super(ctx);
+    this.model = this.ctx.model.Content;
+  }
+  async create({ title, describe, content, bind, istop, date, thumbnail, recommend }) {
+    assert(title, '标题不存在');
+    assert(describe, '描述不存在');
+    assert(content, '内容不存在');
+    assert(bind, '绑定栏目不存在');
+    try {
+      const createAt = moment().format('x');
+      const updateAt = moment().format('x');
+      const item = await this.model.create({ title, describe, content, bind, istop, date, thumbnail, recommend, createAt, updateAt });
+      return { errcode: 0, errmsg: '', data: item };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async update({ id, title, describe, content, bind, istop, date, thumbnail, recommend }) {
+    assert(id, 'id不存在');
+    try {
+      const res = await this.model.findOne({ _id: id });
+      if (!res) return { errcode: -1001, errmsg: '数据不存在', data: '' };
+      const updateAt = moment().format('x');
+      await this.model.updateOne({ _id: id }, { title, describe, content, bind, istop, date, thumbnail, recommend, updateAt });
+      return { errcode: 0, errmsg: '', data: 'update' };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async delete({ id }) {
+    assert(id, 'id不存在');
+    try {
+      const res = await this.model.findOne({ _id: id });
+      if (!res) return { errcode: -1001, errmsg: '数据不存在', data: '' };
+      await this.model.remove({ _id: id });
+      return { errcode: 0, errmsg: '', data: 'delete' };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async query({ skip, limit, title, date }) {
+    const filter = {};
+    if (title || date) filter.$or = [];
+    if (title) filter.$or.push({ code: { $regex: title } });
+    if (date) filter.$or.push({ name: { $regex: date } });
+    try {
+      let res;
+      const total = await this.model.find({ ...filter }, { content: false });
+      if (skip && limit) {
+        res = await this.model.find({ ...filter }, { content: false })
+          .skip(Number(skip) * Number(limit))
+          .limit(Number(limit))
+          .sort({ date: 1 });
+      } else {
+        res = await this.model.find({ ...filter }, { content: false }).sort({ date: 1 });
+      }
+      return { errcode: 0, errmsg: '', data: res, total: total.length };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async fetch({ id }) {
+    try {
+      const res = await this.model.findOne({ _id: id });
+      if (!res) return { errcode: -1001, errmsg: '数据不存在', data: '' };
+      await this.model.update({ _id: id }, { visit: res.visit + 1 });
+      return { errcode: 0, errmsg: '', data: res };
+    } catch (error) {
+      throw error;
+    }
+  }
+}
+
+module.exports = ContentService;

+ 81 - 0
service-cms/app/service/imgnews.js

@@ -0,0 +1,81 @@
+'use strict';
+
+const assert = require('assert');
+const moment = require('moment');
+const Service = require('egg').Service;
+class ImgnewsService extends Service {
+  constructor(ctx) {
+    super(ctx);
+    this.model = this.ctx.model.Imgnews;
+    this.column = this.ctx.model.Column;
+    this.pages = this.ctx.model.Pages;
+  }
+  async create({ type, bind, date, img, url, column, pages }) {
+    assert(type, '类型不存在');
+    assert(bind, '绑定类型不存在');
+    assert(img, '图片不存在');
+    try {
+      const createAt = moment().format('x');
+      const updateAt = moment().format('x');
+      const item = await this.model.create({ type, bind, date, img, url, column, pages, createAt, updateAt });
+      return { errcode: 0, errmsg: '', data: item };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async update({ id, type, bind, date, img, url, column, pages }) {
+    assert(id, 'id不存在');
+    try {
+      const res = await this.model.findOne({ _id: id });
+      if (!res) return { errcode: -1001, errmsg: '数据不存在', data: '' };
+      const updateAt = moment().format('x');
+      await this.model.updateOne({ _id: id }, { type, bind, date, img, url, column, pages, updateAt });
+      return { errcode: 0, errmsg: '', data: 'update' };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async delete({ id }) {
+    assert(id, 'id不存在');
+    try {
+      const res = await this.model.findOne({ _id: id });
+      if (!res) return { errcode: -1001, errmsg: '数据不存在', data: '' };
+      await this.model.remove({ _id: id });
+      return { errcode: 0, errmsg: '', data: 'delete' };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async query({ skip, limit, title, date }) {
+    const filter = {};
+    if (title || date) filter.$or = [];
+    if (title) filter.$or.push({ code: { $regex: title } });
+    if (date) filter.$or.push({ name: { $regex: date } });
+    try {
+      let res;
+      const total = await this.model.find({ ...filter }, { content: false });
+      if (skip && limit) {
+        res = await this.model.find({ ...filter }, { content: false })
+          .skip(Number(skip) * Number(limit))
+          .limit(Number(limit))
+          .sort({ date: 1 });
+      } else {
+        res = await this.model.find({ ...filter }, { content: false }).sort({ date: 1 });
+      }
+      return { errcode: 0, errmsg: '', data: res, total: total.length };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async fetch({ id }) {
+    try {
+      const res = await this.model.findOne({ _id: id });
+      if (!res) return { errcode: -1001, errmsg: '数据不存在', data: '' };
+      return { errcode: 0, errmsg: '', data: res };
+    } catch (error) {
+      throw error;
+    }
+  }
+}
+
+module.exports = ImgnewsService;

+ 67 - 0
service-cms/app/service/imgtype.js

@@ -0,0 +1,67 @@
+'use strict';
+
+const assert = require('assert');
+const Service = require('egg').Service;
+class ImgtypeService extends Service {
+  constructor(ctx) {
+    super(ctx);
+    this.model = this.ctx.model.Imgtype;
+    this.imgnews = this.ctx.model.Imgnews;
+  }
+  async create({ name, code }) {
+    assert(name, '名称不存在');
+    assert(code, '编码不存在');
+    try {
+      const res = await this.model.findOne({ code });
+      if (res) return { errcode: -1001, errmsg: '编码已存在', data: '' };
+      const item = await this.model.create({ name, code });
+      return { errcode: 0, errmsg: '', data: item };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async update({ id, name }) {
+    assert(id, 'id不存在');
+    try {
+      const res = await this.model.findOne({ _id: id });
+      if (!res) return { errcode: -1001, errmsg: '数据不存在', data: '' };
+      await this.model.updateOne({ _id: id }, { name });
+      return { errcode: 0, errmsg: '', data: 'update' };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async delete({ id }) {
+    assert(id, 'id不存在');
+    try {
+      const res = await this.model.findOne({ _id: id });
+      if (!res) return { errcode: -1001, errmsg: '数据不存在', data: '' };
+      const imgnews = await this.imgnews.findOne({ bind: res.code });
+      if (imgnews) return { errcode: -1001, errmsg: '存在绑定关系,不能删除', data: '' };
+      await this.model.remove({ _id: id });
+      return { errcode: 0, errmsg: '', data: 'delete' };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async query({ skip, limit, name, code }) {
+    const filter = {};
+    if (name || code) filter.$or = [];
+    if (name) filter.$or.push({ code: { $regex: name } });
+    if (code) filter.$or.push({ name: { $regex: code } });
+    try {
+      let res;
+      const total = await this.model.find({ ...filter });
+      if (skip && limit) {
+        res = await this.model.find({ ...filter }).skip(Number(skip) * Number(limit)).limit(Number(limit));
+      } else {
+        res = await this.model.find({ ...filter });
+      }
+      return { errcode: 0, errmsg: '', data: res, total: total.length };
+    } catch (error) {
+      throw error;
+    }
+  }
+}
+
+module.exports = ImgtypeService;

+ 73 - 0
service-cms/app/service/menu.js

@@ -0,0 +1,73 @@
+'use strict';
+
+const assert = require('assert');
+const Service = require('egg').Service;
+class MenuService extends Service {
+  constructor(ctx) {
+    super(ctx);
+    this.model = this.ctx.model.Menu;
+    this.column = this.ctx.model.Column;
+    this.pages = this.ctx.model.Pages;
+  }
+  async create({ name, code, sort, type, url, column, pages }) {
+    assert(name, '名称不存在');
+    assert(code, '编码不存在');
+    assert(type, '类型不存在');
+    try {
+      const res = await this.model.findOne({ code });
+      if (res) return { errcode: -1001, errmsg: '编码已存在', data: '' };
+      const item = await this.model.create({ name, code, sort, type, url, column, pages });
+      return { errcode: 0, errmsg: '', data: item };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async update({ id, name, sort, type, url, column, pages }) {
+    assert(id, 'id不存在');
+    try {
+      const res = await this.model.findOne({ _id: id });
+      if (!res) return { errcode: -1001, errmsg: '数据不存在', data: '' };
+      await this.model.updateOne({ _id: id }, { name, sort, type, url, column, pages });
+      return { errcode: 0, errmsg: '', data: 'update' };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async delete({ id }) {
+    assert(id, 'id不存在');
+    try {
+      const res = await this.model.findOne({ _id: id });
+      if (!res) return { errcode: -1001, errmsg: '数据不存在', data: '' };
+      const column = await this.column.findOne({ bind: res.code });
+      const pages = await this.pages.findOne({ bind: res.code });
+      if (column || pages) return { errcode: -1001, errmsg: '存在绑定关系,不能删除', data: '' };
+      await this.model.remove({ _id: id });
+      return { errcode: 0, errmsg: '', data: 'delete' };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async query({ skip, limit, name, code }) {
+    const filter = {};
+    if (name || code) filter.$or = [];
+    if (name) filter.$or.push({ code: { $regex: name } });
+    if (code) filter.$or.push({ name: { $regex: code } });
+    try {
+      let res;
+      const total = await this.model.find({ ...filter });
+      if (skip && limit) {
+        res = await this.model.find({ ...filter })
+          .skip(Number(skip) * Number(limit))
+          .limit(Number(limit))
+          .sort({ date: 1 });
+      } else {
+        res = await this.model.find({ ...filter });
+      }
+      return { errcode: 0, errmsg: '', data: res, total: total.length };
+    } catch (error) {
+      throw error;
+    }
+  }
+}
+
+module.exports = MenuService;

+ 89 - 0
service-cms/app/service/pages.js

@@ -0,0 +1,89 @@
+'use strict';
+
+const assert = require('assert');
+const moment = require('moment');
+const Service = require('egg').Service;
+class PagesService extends Service {
+  constructor(ctx) {
+    super(ctx);
+    this.model = this.ctx.model.Pages;
+    this.menu = this.ctx.model.Menu;
+    this.imgnews = this.ctx.model.Imgnews;
+  }
+  async create({ title, describe, content, code }) {
+    assert(title, '标题不存在');
+    assert(describe, '描述不存在');
+    assert(content, '内容不存在');
+    try {
+      const res = await this.model.findOne({ code });
+      if (res) return { errcode: -1001, errmsg: '编码已存在', data: '' };
+      const createAt = moment().format('x');
+      const updateAt = moment().format('x');
+      const item = await this.model.create({ title, describe, content, code, createAt, updateAt });
+      return { errcode: 0, errmsg: '', data: item };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async update({ id, title, describe, content }) {
+    assert(id, 'id不存在');
+    try {
+      const res = await this.model.findOne({ _id: id });
+      if (!res) return { errcode: -1001, errmsg: '数据不存在', data: '' };
+      const updateAt = moment().format('x');
+      await this.model.updateOne({ _id: id }, { title, describe, content, updateAt });
+      return { errcode: 0, errmsg: '', data: 'update' };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async delete({ id }) {
+    assert(id, 'id不存在');
+    try {
+      const res = await this.model.findOne({ _id: id });
+      if (!res) return { errcode: -1001, errmsg: '数据不存在', data: '' };
+      const menu = await this.menu.findOne({ column: res.code });
+      const imgnews = await this.imgnews.findOne({ column: res.code });
+      if (menu || imgnews) {
+        let errmsg = '';
+        if (menu) errmsg += '(菜单)';
+        if (imgnews) errmsg += '(图片新闻)';
+        return { errcode: -1001, errmsg: `存在${errmsg}绑定关系,不能删除`, data: '' };
+      }
+      await this.model.remove({ _id: id });
+      return { errcode: 0, errmsg: '', data: 'delete' };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async query({ skip, limit, title, code }) {
+    const filter = {};
+    if (title || code) filter.$or = [];
+    if (title) filter.$or.push({ code: { $regex: title } });
+    if (code) filter.$or.push({ code: { $regex: code } });
+    try {
+      let res;
+      const total = await this.model.find({ ...filter }, { content: false });
+      if (skip && limit) {
+        res = await this.model.find({ ...filter }, { content: false }).skip(Number(skip) * Number(limit)).limit(Number(limit));
+      } else {
+        res = await this.model.find({ ...filter }, { content: false });
+      }
+      return { errcode: 0, errmsg: '', data: res, total: total.length };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async fetch({ id }) {
+    try {
+      const res = await this.model.findOne({ _id: id });
+      if (!res) return { errcode: -1001, errmsg: '数据不存在', data: '' };
+      await this.model.updateOne({ _id: id }, { visit: res.visit + 1 });
+      return { errcode: 0, errmsg: '', data: res };
+    } catch (error) {
+      throw error;
+    }
+  }
+}
+
+module.exports = PagesService;

+ 67 - 0
service-cms/app/service/toconfig.js

@@ -0,0 +1,67 @@
+'use strict';
+
+const assert = require('assert');
+const Service = require('egg').Service;
+class ToconfigService extends Service {
+  constructor(ctx) {
+    super(ctx);
+    this.model = this.ctx.model.Type;
+    this.codeModel = this.ctx.model.Dictionary;
+  }
+  async create({ name, code, type, value }) {
+    assert(name, '名称不存在');
+    assert(code, '编码不存在');
+    assert(type, '类型不存在');
+    assert(value, '值不存在');
+    try {
+      const res = await this.findOne({ code });
+      if (res) return { errcode: -1001, errmsg: '编码已存在', data: '' };
+      const item = await this.model.create({ name, code, type, value });
+      return { errcode: 0, errmsg: '', data: item };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async update({ id, name, type, value }) {
+    assert(id, 'id不存在');
+    try {
+      const res = await this.findOne({ _id: id });
+      if (!res) return { errcode: -1001, errmsg: '数据不存在', data: '' };
+      await this.model.updateOne({ _id: id }, { name, type, value });
+      return { errcode: 0, errmsg: '', data: 'update' };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async delete({ id }) {
+    assert(id, 'id不存在');
+    try {
+      const res = await this.findOne({ _id: id });
+      if (!res) return { errcode: -1001, errmsg: '数据不存在', data: '' };
+      await this.model.remove({ _id: id });
+      return { errcode: 0, errmsg: '', data: 'delete' };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async query({ skip, limit, name, code }) {
+    const filter = {};
+    if (name || code) filter.$or = [];
+    if (name) filter.$or.push({ code: { $regex: name } });
+    if (code) filter.$or.push({ name: { $regex: code } });
+    try {
+      let res;
+      const total = await this.model.find({ ...filter });
+      if (skip && limit) {
+        res = await this.model.find({ ...filter }).skip(Number(skip) * Number(limit)).limit(Number(limit));
+      } else {
+        res = await this.model.find({ ...filter });
+      }
+      return { errcode: 0, errmsg: '', data: res, total: total.length };
+    } catch (error) {
+      throw error;
+    }
+  }
+}
+
+module.exports = ToconfigService;

+ 14 - 0
service-cms/appveyor.yml

@@ -0,0 +1,14 @@
+environment:
+  matrix:
+    - nodejs_version: '10'
+
+install:
+  - ps: Install-Product node $env:nodejs_version
+  - npm i npminstall && node_modules\.bin\npminstall
+
+test_script:
+  - node --version
+  - npm --version
+  - npm run test
+
+build: off

+ 52 - 0
service-cms/config/config.default.js

@@ -0,0 +1,52 @@
+/* eslint valid-jsdoc: "off" */
+
+'use strict';
+
+/**
+ * @param {Egg.EggAppInfo} appInfo app info
+ */
+module.exports = appInfo => {
+  /**
+   * built-in config
+   * @type {Egg.EggAppConfig}
+   **/
+  const config = exports = {};
+
+  // use for cookie sign key, should change to your own and keep security
+  config.keys = appInfo.name + '_1636677178960_3010';
+
+  // add your middleware config here
+  config.middleware = [];
+
+  // add your user config here
+  const userConfig = {
+    // myAppName: 'egg',
+  };
+  // 安全配置
+  config.security = {
+    csrf: {
+      // ignoreJSON: true, // 默认为 false,当设置为 true 时,将会放过所有 content-type 为 `application/json` 的请求
+      enable: false,
+    },
+  };
+  config.cluster = {
+    listen: {
+      port: 9004,
+    },
+  };
+  // 数据库配置
+  config.mongoose = {
+    url: 'mongodb://127.0.0.1/Microservices',
+    options: {
+      // user: 'root',
+      // pass: 'cms@cc-lotus',
+      // authSource: 'admin',
+      // useNewUrlParser: true,
+      // useCreateIndex: true,
+    },
+  };
+  return {
+    ...config,
+    ...userConfig,
+  };
+};

+ 9 - 0
service-cms/config/plugin.js

@@ -0,0 +1,9 @@
+'use strict';
+
+/** @type Egg.EggPlugin */
+module.exports = {
+  mongoose: {
+    enable: true,
+    package: 'egg-mongoose',
+  },
+};

+ 17 - 0
service-cms/ecosystem.config.js

@@ -0,0 +1,17 @@
+'use strict';
+
+const app = 'service-cms';
+module.exports = {
+  apps: [{
+    name: app, // 应用名称
+    script: './server.js', // 实际启动脚本
+    out: `./logs/${app}.log`,
+    error: `./logs/${app}.err`,
+    watch: [ // 监控变化的目录,一旦变化,自动重启
+      'app', 'config',
+    ],
+    env: {
+      NODE_ENV: process.env.NODE_ENV || 'production', // 环境参数,当前指定为生产环境
+    },
+  }],
+};

+ 5 - 0
service-cms/jsconfig.json

@@ -0,0 +1,5 @@
+{
+  "include": [
+    "**/*"
+  ]
+}

+ 48 - 0
service-cms/package.json

@@ -0,0 +1,48 @@
+{
+  "name": "service-cms",
+  "version": "1.0.0",
+  "description": "",
+  "private": true,
+  "egg": {
+    "declarations": true
+  },
+  "dependencies": {
+    "egg": "^2.15.1",
+    "egg-mongoose": "^3.3.1",
+    "egg-scripts": "^2.11.0",
+    "moment": "^2.29.1"
+  },
+  "devDependencies": {
+    "autod": "^3.0.1",
+    "autod-egg": "^1.1.0",
+    "egg-bin": "^4.11.0",
+    "egg-ci": "^1.11.0",
+    "egg-mock": "^3.21.0",
+    "eslint": "^5.13.0",
+    "eslint-config-egg": "^7.1.0"
+  },
+  "engines": {
+    "node": ">=10.0.0"
+  },
+  "scripts": {
+    "start": "egg-scripts start --daemon --title=egg-server-service-cms",
+    "stop": "egg-scripts stop --title=egg-server-service-cms",
+    "dev": "egg-bin dev",
+    "debug": "egg-bin debug",
+    "test": "npm run lint -- --fix && npm run test-local",
+    "test-local": "egg-bin test",
+    "cov": "egg-bin cov",
+    "lint": "eslint .",
+    "ci": "npm run lint && npm run cov",
+    "autod": "autod"
+  },
+  "ci": {
+    "version": "10"
+  },
+  "repository": {
+    "type": "git",
+    "url": ""
+  },
+  "author": "",
+  "license": "MIT"
+}

+ 9 - 0
service-cms/server.js

@@ -0,0 +1,9 @@
+
+// eslint-disable-next-line strict
+const egg = require('egg');
+
+const workers = Number(process.argv[2] || require('os').cpus().length);
+egg.startCluster({
+  workers,
+  baseDir: __dirname,
+});

+ 20 - 0
service-cms/test/app/controller/home.test.js

@@ -0,0 +1,20 @@
+'use strict';
+
+const { app, assert } = require('egg-mock/bootstrap');
+
+describe('test/app/controller/home.test.js', () => {
+  it('should assert', () => {
+    const pkg = require('../../../package.json');
+    assert(app.config.keys.startsWith(pkg.name));
+
+    // const ctx = app.mockContext({});
+    // yield ctx.service.xx();
+  });
+
+  it('should GET /', () => {
+    return app.httpRequest()
+      .get('/')
+      .expect('hi, egg')
+      .expect(200);
+  });
+});

+ 29 - 0
service-code/.autod.conf.js

@@ -0,0 +1,29 @@
+'use strict';
+
+module.exports = {
+  write: true,
+  prefix: '^',
+  plugin: 'autod-egg',
+  test: [
+    'test',
+    'benchmark',
+  ],
+  dep: [
+    'egg',
+    'egg-scripts',
+  ],
+  devdep: [
+    'egg-ci',
+    'egg-bin',
+    'egg-mock',
+    'autod',
+    'autod-egg',
+    'eslint',
+    'eslint-config-egg',
+  ],
+  exclude: [
+    './test/fixtures',
+    './dist',
+  ],
+};
+

+ 1 - 0
service-code/.eslintignore

@@ -0,0 +1 @@
+coverage

+ 3 - 0
service-code/.eslintrc

@@ -0,0 +1,3 @@
+{
+  "extends": "eslint-config-egg"
+}

+ 46 - 0
service-code/.github/workflows/nodejs.yml

@@ -0,0 +1,46 @@
+# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
+# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
+
+name: Node.js CI
+
+on:
+  push:
+    branches:
+      - main
+      - master
+  pull_request:
+    branches:
+      - main
+      - master
+  schedule:
+    - cron: '0 2 * * *'
+
+jobs:
+  build:
+    runs-on: ${{ matrix.os }}
+
+    strategy:
+      fail-fast: false
+      matrix:
+        node-version: [10]
+        os: [ubuntu-latest, windows-latest, macos-latest]
+
+    steps:
+    - name: Checkout Git Source
+      uses: actions/checkout@v2
+
+    - name: Use Node.js ${{ matrix.node-version }}
+      uses: actions/setup-node@v1
+      with:
+        node-version: ${{ matrix.node-version }}
+
+    - name: Install Dependencies
+      run: npm i -g npminstall && npminstall
+
+    - name: Continuous Integration
+      run: npm run ci
+
+    - name: Code Coverage
+      uses: codecov/codecov-action@v1
+      with:
+        token: ${{ secrets.CODECOV_TOKEN }}

+ 14 - 0
service-code/.gitignore

@@ -0,0 +1,14 @@
+logs/
+npm-debug.log
+yarn-error.log
+node_modules/
+package-lock.json
+yarn.lock
+coverage/
+.idea/
+run/
+.DS_Store
+*.sw*
+*.un~
+typings/
+.nyc_output/

+ 12 - 0
service-code/.travis.yml

@@ -0,0 +1,12 @@
+
+language: node_js
+node_js:
+  - '10'
+before_install:
+  - npm i npminstall -g
+install:
+  - npminstall
+script:
+  - npm run ci
+after_script:
+  - npminstall codecov && codecov

+ 33 - 0
service-code/README.md

@@ -0,0 +1,33 @@
+# service-code
+
+
+
+## QuickStart
+
+<!-- add docs here for user -->
+
+see [egg docs][egg] for more detail.
+
+### Development
+
+```bash
+$ npm i
+$ npm run dev
+$ open http://localhost:7001/
+```
+
+### Deploy
+
+```bash
+$ npm start
+$ npm stop
+```
+
+### npm scripts
+
+- Use `npm run lint` to check code style.
+- Use `npm test` to run unit test.
+- Use `npm run autod` to auto detect dependencies upgrade, see [autod](https://www.npmjs.com/package/autod) for more detail.
+
+
+[egg]: https://eggjs.org

+ 23 - 0
service-code/app/controller/dictionary.js

@@ -0,0 +1,23 @@
+'use strict';
+const Controller = require('egg').Controller;
+
+class DictionaryController extends Controller {
+  async create() {
+    const res = await this.ctx.service.dictionary.create(this.ctx.request.body);
+    this.ctx.body = res;
+  }
+  async update() {
+    const res = await this.ctx.service.dictionary.update(this.ctx.request.body);
+    this.ctx.body = res;
+  }
+  async delete() {
+    const res = await this.ctx.service.dictionary.delete(this.ctx.params);
+    this.ctx.body = res;
+  }
+  async query() {
+    const res = await this.ctx.service.dictionary.query(this.ctx.query);
+    this.ctx.body = res;
+  }
+}
+
+module.exports = DictionaryController;

+ 24 - 0
service-code/app/controller/type.js

@@ -0,0 +1,24 @@
+'use strict';
+const Controller = require('egg').Controller;
+
+class TypeController extends Controller {
+  async create() {
+    const res = await this.ctx.service.type.create(this.ctx.request.body);
+    this.ctx.body = res;
+  }
+  async update() {
+    const res = await this.ctx.service.type.update(this.ctx.request.body);
+    this.ctx.body = res;
+  }
+  async delete() {
+    console.log(123);
+    const res = await this.ctx.service.type.delete(this.ctx.params);
+    this.ctx.body = res;
+  }
+  async query() {
+    const res = await this.ctx.service.type.query(this.ctx.query);
+    this.ctx.body = res;
+  }
+}
+
+module.exports = TypeController;

+ 12 - 0
service-code/app/model/dictionary.js

@@ -0,0 +1,12 @@
+'use strict';
+const Schema = require('mongoose').Schema;
+const SchemaDefine = {
+  code: { type: String, required: true },
+  name: { type: String, required: true },
+  parentCode: { type: String, required: true },
+};
+const schema = new Schema(SchemaDefine);
+module.exports = app => {
+  const { mongoose } = app;
+  return mongoose.model('dictionary', schema, 'dictionary');
+};

+ 11 - 0
service-code/app/model/type.js

@@ -0,0 +1,11 @@
+'use strict';
+const Schema = require('mongoose').Schema;
+const SchemaDefine = {
+  code: { type: String, required: true },
+  name: { type: String, required: true },
+};
+const schema = new Schema(SchemaDefine);
+module.exports = app => {
+  const { mongoose } = app;
+  return mongoose.model('type', schema, 'type');
+};

+ 18 - 0
service-code/app/router.js

@@ -0,0 +1,18 @@
+'use strict';
+
+/**
+ * @param {Egg.Application} app - egg application
+ */
+module.exports = app => {
+  const { router, controller } = app;
+  // 类型
+  router.post('/api/code/type/create', controller.type.create);
+  router.post('/api/code/type/update', controller.type.update);
+  router.delete('/api/code/type/delete/:id', controller.type.delete);
+  router.get('/api/code/type/query', controller.type.query);
+  // 字典项
+  router.post('/api/code/dictionary/create', controller.dictionary.create);
+  router.post('/api/code/dictionary/update', controller.dictionary.update);
+  router.delete('/api/code/dictionary/delete/:id', controller.dictionary.delete);
+  router.get('/api/code/dictionary/query', controller.dictionary.query);
+};

+ 65 - 0
service-code/app/service/dictionary.js

@@ -0,0 +1,65 @@
+'use strict';
+
+const assert = require('assert');
+const Service = require('egg').Service;
+class DictionaryService extends Service {
+  constructor(ctx) {
+    super(ctx, 'dictionary');
+    this.model = this.ctx.model.Dictionary;
+    this.TypeModel = this.ctx.model.Type;
+  }
+  async create({ name, code, parentCode }) {
+    assert(name, '名称不存在');
+    assert(code, '编码不存在');
+    assert(parentCode, '类型编码不存在');
+    try {
+      const parent = await this.TypeModel.findOne({ code: parentCode });
+      if (!parent) return { errcode: -1001, errmsg: '父级编码不存在', data: '' };
+      const obj = await this.model.findOne({ code });
+      if (obj) return { errcode: -1001, errmsg: '编码已存在', data: '' };
+      const res = await this.model.create({ name, code, parentCode });
+      return { errcode: 0, errmsg: 'ok', data: res };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async update({ id, name, code }) {
+    assert(id, 'id不存在');
+    try {
+      await this.model.updateOne({ _id: id }, { name, code });
+      return { errcode: 0, errmsg: 'ok', data: '' };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async delete({ id }) {
+    assert(id, 'id不存在');
+    try {
+      await this.model.remove({ _id: id });
+      return { errcode: 0, errmsg: 'ok', data: '' };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async query({ skip, limit, parentCode, code, name }) {
+    const filter = {};
+    if (code || name) filter.$or = [];
+    if (code) filter.$or.push({ code: { $regex: code } });
+    if (name) filter.$or.push({ name: { $regex: name } });
+    if (parentCode) filter.parentCode = parentCode;
+    try {
+      const total = await this.model.find({ ...filter });
+      let res;
+      if (skip && limit) {
+        res = await this.model.find({ ...filter }).skip(Number(skip) * Number(limit)).limit(Number(limit));
+      } else {
+        res = await this.model.find({ ...filter });
+      }
+      return { errcode: 0, errmsg: 'ok', data: res, total: total.length };
+    } catch (error) {
+      throw error;
+    }
+  }
+}
+
+module.exports = DictionaryService;

+ 65 - 0
service-code/app/service/type.js

@@ -0,0 +1,65 @@
+'use strict';
+
+const assert = require('assert');
+const Service = require('egg').Service;
+class TypeService extends Service {
+  constructor(ctx) {
+    super(ctx);
+    this.model = this.ctx.model.Type;
+    this.codeModel = this.ctx.model.Dictionary;
+  }
+  async create({ name, code }) {
+    assert(name, '名称不存在');
+    assert(code, '编码不存在');
+    try {
+      const obj = await this.model.findOne({ code });
+      if (obj) return { errcode: -1001, errmsg: '编码已存在', data: '' };
+      const res = await this.model.create({ name, code });
+      return { errcode: 0, errmsg: 'ok', data: res };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async update({ id, name, code }) {
+    assert(id, 'id不存在');
+    try {
+      await this.model.updateOne({ _id: id }, { name, code });
+      return { errcode: 0, errmsg: 'ok', data: '' };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async delete({ id }) {
+    console.log(id);
+    assert(id, 'id不存在');
+    try {
+      const res = await this.model.findOne({ _id: id });
+      const codeList = await this.codeModel.find({ parentCode: res.code });
+      if (codeList.length > 0) await this.codeModel.remove({ parentCode: res.code });
+      await this.model.remove({ _id: id });
+      return { errcode: 0, errmsg: 'ok', data: '' };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async query({ skip, limit, code, name }) {
+    const filter = {};
+    if (code || name) filter.$or = [];
+    if (code) filter.$or.push({ code: { $regex: code } });
+    if (name) filter.$or.push({ name: { $regex: name } });
+    try {
+      const total = await this.model.find({ ...filter });
+      let res;
+      if (skip && limit) {
+        res = await this.model.find({ ...filter }).skip(Number(skip) * Number(limit)).limit(Number(limit));
+      } else {
+        res = await this.model.find({ ...filter });
+      }
+      return { errcode: 0, errmsg: 'ok', data: res, total: total.length };
+    } catch (error) {
+      throw error;
+    }
+  }
+}
+
+module.exports = TypeService;

+ 14 - 0
service-code/appveyor.yml

@@ -0,0 +1,14 @@
+environment:
+  matrix:
+    - nodejs_version: '10'
+
+install:
+  - ps: Install-Product node $env:nodejs_version
+  - npm i npminstall && node_modules\.bin\npminstall
+
+test_script:
+  - node --version
+  - npm --version
+  - npm run test
+
+build: off

+ 54 - 0
service-code/config/config.default.js

@@ -0,0 +1,54 @@
+/* eslint valid-jsdoc: "off" */
+
+'use strict';
+
+/**
+ * @param {Egg.EggAppInfo} appInfo app info
+ */
+module.exports = appInfo => {
+  /**
+   * built-in config
+   * @type {Egg.EggAppConfig}
+   **/
+  const config = exports = {};
+
+  // use for cookie sign key, should change to your own and keep security
+  config.keys = appInfo.name + '_1635902541751_9477';
+
+  // add your middleware config here
+  config.middleware = [];
+  // add your user config here
+  const userConfig = {
+    // myAppName: 'egg',
+  };
+  // 安全配置
+  config.security = {
+    csrf: {
+      // ignoreJSON: true, // 默认为 false,当设置为 true 时,将会放过所有 content-type 为 `application/json` 的请求
+      enable: false,
+    },
+  };
+  config.cluster = {
+    listen: {
+      port: 9001,
+    },
+  };
+  // 数据库配置
+  config.mongoose = {
+    url: 'mongodb://127.0.0.1/Microservices',
+    options: {
+      // user: 'root',
+      // pass: 'cms@cc-lotus',
+      // authSource: 'admin',
+      // useNewUrlParser: true,
+      // useCreateIndex: true,
+    },
+  };
+  config.logger = {
+    level: 'DEBUG',
+  };
+  return {
+    ...config,
+    ...userConfig,
+  };
+};

+ 9 - 0
service-code/config/plugin.js

@@ -0,0 +1,9 @@
+'use strict';
+
+/** @type Egg.EggPlugin */
+module.exports = {
+  mongoose: {
+    enable: true,
+    package: 'egg-mongoose',
+  },
+};

+ 17 - 0
service-code/ecosystem.config.js

@@ -0,0 +1,17 @@
+'use strict';
+
+const app = 'service-code';
+module.exports = {
+  apps: [{
+    name: app, // 应用名称
+    script: './server.js', // 实际启动脚本
+    out: `./logs/${app}.log`,
+    error: `./logs/${app}.err`,
+    watch: [ // 监控变化的目录,一旦变化,自动重启
+      'app', 'config',
+    ],
+    env: {
+      NODE_ENV: process.env.NODE_ENV || 'production', // 环境参数,当前指定为生产环境
+    },
+  }],
+};

+ 5 - 0
service-code/jsconfig.json

@@ -0,0 +1,5 @@
+{
+  "include": [
+    "**/*"
+  ]
+}

+ 47 - 0
service-code/package.json

@@ -0,0 +1,47 @@
+{
+  "name": "service-code",
+  "version": "1.0.0",
+  "description": "",
+  "private": true,
+  "egg": {
+    "declarations": true
+  },
+  "dependencies": {
+    "egg": "^2.15.1",
+    "egg-mongoose": "^3.3.1",
+    "egg-scripts": "^2.11.0"
+  },
+  "devDependencies": {
+    "autod": "^3.0.1",
+    "autod-egg": "^1.1.0",
+    "egg-bin": "^4.11.0",
+    "egg-ci": "^1.11.0",
+    "egg-mock": "^3.21.0",
+    "eslint": "^5.13.0",
+    "eslint-config-egg": "^7.1.0"
+  },
+  "engines": {
+    "node": ">=10.0.0"
+  },
+  "scripts": {
+    "start": "egg-scripts start --daemon --title=egg-server-service-code",
+    "stop": "egg-scripts stop --title=egg-server-service-code",
+    "dev": "egg-bin dev",
+    "debug": "egg-bin debug",
+    "test": "npm run lint -- --fix && npm run test-local",
+    "test-local": "egg-bin test",
+    "cov": "egg-bin cov",
+    "lint": "eslint .",
+    "ci": "npm run lint && npm run cov",
+    "autod": "autod"
+  },
+  "ci": {
+    "version": "10"
+  },
+  "repository": {
+    "type": "git",
+    "url": ""
+  },
+  "author": "",
+  "license": "MIT"
+}

+ 9 - 0
service-code/server.js

@@ -0,0 +1,9 @@
+
+// eslint-disable-next-line strict
+const egg = require('egg');
+
+const workers = Number(process.argv[2] || require('os').cpus().length);
+egg.startCluster({
+  workers,
+  baseDir: __dirname,
+});

+ 20 - 0
service-code/test/app/controller/home.test.js

@@ -0,0 +1,20 @@
+'use strict';
+
+const { app, assert } = require('egg-mock/bootstrap');
+
+describe('test/app/controller/home.test.js', () => {
+  it('should assert', () => {
+    const pkg = require('../../../package.json');
+    assert(app.config.keys.startsWith(pkg.name));
+
+    // const ctx = app.mockContext({});
+    // yield ctx.service.xx();
+  });
+
+  it('should GET /', () => {
+    return app.httpRequest()
+      .get('/')
+      .expect('hi, egg')
+      .expect(200);
+  });
+});

+ 29 - 0
service-files/.autod.conf.js

@@ -0,0 +1,29 @@
+'use strict';
+
+module.exports = {
+  write: true,
+  prefix: '^',
+  plugin: 'autod-egg',
+  test: [
+    'test',
+    'benchmark',
+  ],
+  dep: [
+    'egg',
+    'egg-scripts',
+  ],
+  devdep: [
+    'egg-ci',
+    'egg-bin',
+    'egg-mock',
+    'autod',
+    'autod-egg',
+    'eslint',
+    'eslint-config-egg',
+  ],
+  exclude: [
+    './test/fixtures',
+    './dist',
+  ],
+};
+

+ 1 - 0
service-files/.eslintignore

@@ -0,0 +1 @@
+coverage

+ 3 - 0
service-files/.eslintrc

@@ -0,0 +1,3 @@
+{
+  "extends": "eslint-config-egg"
+}

+ 14 - 0
service-files/.gitignore

@@ -0,0 +1,14 @@
+logs/
+npm-debug.log
+yarn-error.log
+node_modules/
+package-lock.json
+yarn.lock
+coverage/
+.idea/
+run/
+.DS_Store
+*.sw*
+*.un~
+typings/
+.nyc_output/

+ 12 - 0
service-files/.travis.yml

@@ -0,0 +1,12 @@
+
+language: node_js
+node_js:
+  - '10'
+before_install:
+  - npm i npminstall -g
+install:
+  - npminstall
+script:
+  - npm run ci
+after_script:
+  - npminstall codecov && codecov

+ 33 - 0
service-files/README.md

@@ -0,0 +1,33 @@
+# service-files
+
+
+
+## QuickStart
+
+<!-- add docs here for user -->
+
+see [egg docs][egg] for more detail.
+
+### Development
+
+```bash
+$ npm i
+$ npm run dev
+$ open http://localhost:7001/
+```
+
+### Deploy
+
+```bash
+$ npm start
+$ npm stop
+```
+
+### npm scripts
+
+- Use `npm run lint` to check code style.
+- Use `npm test` to run unit test.
+- Use `npm run autod` to auto detect dependencies upgrade, see [autod](https://www.npmjs.com/package/autod) for more detail.
+
+
+[egg]: https://eggjs.org

+ 19 - 0
service-files/app/controller/filestore.js

@@ -0,0 +1,19 @@
+'use strict';
+const Controller = require('egg').Controller;
+
+class FilestoreController extends Controller {
+  async upload() {
+    const res = await this.ctx.service.filestore.upload(this.ctx.params);
+    this.ctx.body = res;
+  }
+  async delete() {
+    const res = await this.ctx.service.filestore.delete(this.ctx.request.body);
+    this.ctx.body = res;
+  }
+  async query() {
+    const res = await this.ctx.service.filestore.query(this.ctx.query);
+    this.ctx.body = res;
+  }
+}
+
+module.exports = FilestoreController;

+ 12 - 0
service-files/app/model/filestore.js

@@ -0,0 +1,12 @@
+'use strict';
+const Schema = require('mongoose').Schema;
+const SchemaDefine = {
+  filePath: { type: String, required: true },
+  name: { type: String, required: true },
+  fileName: { type: String, required: true },
+};
+const schema = new Schema(SchemaDefine);
+module.exports = app => {
+  const { mongoose } = app;
+  return mongoose.model('filestore', schema, 'filestore');
+};

+ 11 - 0
service-files/app/router.js

@@ -0,0 +1,11 @@
+'use strict';
+
+/**
+ * @param {Egg.Application} app - egg application
+ */
+module.exports = app => {
+  const { router, controller } = app;
+  router.post('/api/files/:app/upload', controller.filestore.upload);
+  router.post('/api/files/filestore/delete', controller.filestore.delete);
+  router.get('/api/files/filestore/query', controller.filestore.query);
+};

+ 84 - 0
service-files/app/service/filestore.js

@@ -0,0 +1,84 @@
+'use strict';
+
+const fs = require('fs');
+const { extname, sep } = require('path');
+const moment = require('moment');
+const awaitWriteStream = require('await-stream-ready').write;
+const sendToWormhole = require('stream-wormhole');
+const Service = require('egg').Service;
+class FilestoreService extends Service {
+  constructor(ctx) {
+    super(ctx);
+    this.model = this.ctx.model.Filestore;
+  }
+  async upload({ app }) {
+    const stream = await this.ctx.getFileStream();
+    console.log(app);
+    const rootPath = `${this.app.config.repos_root_path}`;
+    // 检查路径是否存在,不存在则创建
+    if (!fs.existsSync(`${rootPath}/${app}`)) {
+      fs.mkdirSync(`${rootPath}/${app}`);
+    }
+    // 后缀名
+    const ext = extname(stream.filename).toLowerCase();
+    // 制作时间串
+    const name = moment().format('YYYYMMDDHHmmss');
+    // 定义文件名与路径
+    const fileName = `${name}${ext}`;
+    const filePath = `${rootPath}${sep}${app}${sep}`;
+    const writeStream = fs.createWriteStream(filePath + fileName);
+    try {
+      await awaitWriteStream(stream.pipe(writeStream));
+      if (this.app.config.data_save) {
+        return await this.create({ fileName, filePath, name: stream.filename });
+      }
+      const data = { fileName, filePath, name: stream.filename };
+      return { errcode: 0, errmsg: 'ok', data };
+    } catch (error) {
+      await sendToWormhole(stream);
+      throw error;
+    }
+  }
+  async create({ fileName, filePath, name }) {
+    try {
+      const res = await this.model.create({ fileName, filePath, name });
+      return { errcode: 0, errmsg: 'ok', data: res };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async delete({ fileName, filePath }) {
+    try {
+      const file = await fs.existsSync(`${filePath}${fileName}`, exists => {
+        console.log(exists, 'exists');
+        if (!exists) throw { errcode: -1001, errmsg: '文件不存在' };
+      });
+      if (file) {
+        fs.unlink(`${filePath}${fileName}`, err => {
+          if (err) throw { errcode: -2001, errmsg: err };
+        });
+        await this.model.remove({ fileName });
+        return { errcode: 0, errmsg: 'ok' };
+      }
+      return { errcode: -1001, errmsg: '文件不存在' };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async query({ skip, limit, filter }) {
+    try {
+      let res;
+      const total = await this.model.find({ ...filter });
+      if (skip && limit) {
+        res = await this.model.find({ ...filter }).skip(skip * limit);
+      } else {
+        res = await this.model.find({ ...filter });
+      }
+      return { errcode: 0, errmsg: 'ok', data: res, total: total.length };
+    } catch (error) {
+      throw error;
+    }
+  }
+}
+
+module.exports = FilestoreService;

+ 14 - 0
service-files/appveyor.yml

@@ -0,0 +1,14 @@
+environment:
+  matrix:
+    - nodejs_version: '10'
+
+install:
+  - ps: Install-Product node $env:nodejs_version
+  - npm i npminstall && node_modules\.bin\npminstall
+
+test_script:
+  - node --version
+  - npm --version
+  - npm run test
+
+build: off

+ 67 - 0
service-files/config/config.default.js

@@ -0,0 +1,67 @@
+/* eslint valid-jsdoc: "off" */
+
+'use strict';
+
+/**
+ * @param {Egg.EggAppInfo} appInfo app info
+ */
+const { sep } = require('path');
+module.exports = appInfo => {
+  /**
+   * built-in config
+   * @type {Egg.EggAppConfig}
+   **/
+  const config = exports = {};
+
+  // use for cookie sign key, should change to your own and keep security
+  config.keys = appInfo.name + '_1636338746694_9710';
+
+  // add your middleware config here
+  config.middleware = [];
+
+  // add your user config here
+  const userConfig = {
+    // myAppName: 'egg',
+  };
+  // 安全配置
+  config.security = {
+    csrf: {
+      // ignoreJSON: true, // 默认为 false,当设置为 true 时,将会放过所有 content-type 为 `application/json` 的请求
+      enable: false,
+    },
+  };
+  config.cluster = {
+    listen: {
+      port: 9002,
+    },
+  };
+  // 数据库配置
+  config.mongoose = {
+    url: 'mongodb://127.0.0.1/Microservices',
+    options: {
+      // user: 'root',
+      // pass: 'cms@cc-lotus',
+      // authSource: 'admin',
+      // useNewUrlParser: true,
+      // useCreateIndex: true,
+    },
+  };
+  // 文件存储路径
+  config.repos_root_path = `${appInfo.baseDir}${sep}upload`;
+  // 是否启用持久化数据
+  config.data_save = true;
+  // 限制文件大小
+  config.multipart = {
+    mode: 'stream',
+    fileSize: '5mb',
+    fileExtensions: [ '.zip' ], // 新增允许接收的文件后缀
+    // whitelist: [], // 覆盖允许接收的文件后缀
+  };
+  config.logger = {
+    level: 'DEBUG',
+  };
+  return {
+    ...config,
+    ...userConfig,
+  };
+};

+ 9 - 0
service-files/config/plugin.js

@@ -0,0 +1,9 @@
+'use strict';
+
+/** @type Egg.EggPlugin */
+module.exports = {
+  mongoose: {
+    enable: true,
+    package: 'egg-mongoose',
+  },
+};

+ 17 - 0
service-files/ecosystem.config.js

@@ -0,0 +1,17 @@
+'use strict';
+
+const app = 'service-files';
+module.exports = {
+  apps: [{
+    name: app, // 应用名称
+    script: './server.js', // 实际启动脚本
+    out: `./logs/${app}.log`,
+    error: `./logs/${app}.err`,
+    watch: [ // 监控变化的目录,一旦变化,自动重启
+      'app', 'config',
+    ],
+    env: {
+      NODE_ENV: process.env.NODE_ENV || 'production', // 环境参数,当前指定为生产环境
+    },
+  }],
+};

+ 5 - 0
service-files/jsconfig.json

@@ -0,0 +1,5 @@
+{
+  "include": [
+    "**/*"
+  ]
+}

+ 50 - 0
service-files/package.json

@@ -0,0 +1,50 @@
+{
+  "name": "service-files",
+  "version": "1.0.0",
+  "description": "",
+  "private": true,
+  "egg": {
+    "declarations": true
+  },
+  "dependencies": {
+    "await-stream-ready": "^1.0.1",
+    "egg": "^2.15.1",
+    "egg-mongoose": "^3.3.1",
+    "egg-scripts": "^2.11.0",
+    "moment": "^2.29.1",
+    "stream-wormhole": "^1.1.0"
+  },
+  "devDependencies": {
+    "autod": "^3.0.1",
+    "autod-egg": "^1.1.0",
+    "egg-bin": "^4.11.0",
+    "egg-ci": "^1.11.0",
+    "egg-mock": "^3.21.0",
+    "eslint": "^5.13.0",
+    "eslint-config-egg": "^7.1.0"
+  },
+  "engines": {
+    "node": ">=10.0.0"
+  },
+  "scripts": {
+    "start": "egg-scripts start --daemon --title=egg-server-service-files",
+    "stop": "egg-scripts stop --title=egg-server-service-files",
+    "dev": "egg-bin dev",
+    "debug": "egg-bin debug",
+    "test": "npm run lint -- --fix && npm run test-local",
+    "test-local": "egg-bin test",
+    "cov": "egg-bin cov",
+    "lint": "eslint .",
+    "ci": "npm run lint && npm run cov",
+    "autod": "autod"
+  },
+  "ci": {
+    "version": "10"
+  },
+  "repository": {
+    "type": "git",
+    "url": ""
+  },
+  "author": "",
+  "license": "MIT"
+}

+ 9 - 0
service-files/server.js

@@ -0,0 +1,9 @@
+
+// eslint-disable-next-line strict
+const egg = require('egg');
+
+const workers = Number(process.argv[2] || require('os').cpus().length);
+egg.startCluster({
+  workers,
+  baseDir: __dirname,
+});

+ 20 - 0
service-files/test/app/controller/home.test.js

@@ -0,0 +1,20 @@
+'use strict';
+
+const { app, assert } = require('egg-mock/bootstrap');
+
+describe('test/app/controller/home.test.js', () => {
+  it('should assert', () => {
+    const pkg = require('../../../package.json');
+    assert(app.config.keys.startsWith(pkg.name));
+
+    // const ctx = app.mockContext({});
+    // yield ctx.service.xx();
+  });
+
+  it('should GET /', () => {
+    return app.httpRequest()
+      .get('/')
+      .expect('hi, egg')
+      .expect(200);
+  });
+});

+ 29 - 0
service-gateway/.autod.conf.js

@@ -0,0 +1,29 @@
+'use strict';
+
+module.exports = {
+  write: true,
+  prefix: '^',
+  plugin: 'autod-egg',
+  test: [
+    'test',
+    'benchmark',
+  ],
+  dep: [
+    'egg',
+    'egg-scripts',
+  ],
+  devdep: [
+    'egg-ci',
+    'egg-bin',
+    'egg-mock',
+    'autod',
+    'autod-egg',
+    'eslint',
+    'eslint-config-egg',
+  ],
+  exclude: [
+    './test/fixtures',
+    './dist',
+  ],
+};
+

+ 1 - 0
service-gateway/.eslintignore

@@ -0,0 +1 @@
+coverage

+ 3 - 0
service-gateway/.eslintrc

@@ -0,0 +1,3 @@
+{
+  "extends": "eslint-config-egg"
+}

+ 46 - 0
service-gateway/.github/workflows/nodejs.yml

@@ -0,0 +1,46 @@
+# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
+# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
+
+name: Node.js CI
+
+on:
+  push:
+    branches:
+      - main
+      - master
+  pull_request:
+    branches:
+      - main
+      - master
+  schedule:
+    - cron: '0 2 * * *'
+
+jobs:
+  build:
+    runs-on: ${{ matrix.os }}
+
+    strategy:
+      fail-fast: false
+      matrix:
+        node-version: [10]
+        os: [ubuntu-latest, windows-latest, macos-latest]
+
+    steps:
+    - name: Checkout Git Source
+      uses: actions/checkout@v2
+
+    - name: Use Node.js ${{ matrix.node-version }}
+      uses: actions/setup-node@v1
+      with:
+        node-version: ${{ matrix.node-version }}
+
+    - name: Install Dependencies
+      run: npm i -g npminstall && npminstall
+
+    - name: Continuous Integration
+      run: npm run ci
+
+    - name: Code Coverage
+      uses: codecov/codecov-action@v1
+      with:
+        token: ${{ secrets.CODECOV_TOKEN }}

+ 14 - 0
service-gateway/.gitignore

@@ -0,0 +1,14 @@
+logs/
+npm-debug.log
+yarn-error.log
+node_modules/
+package-lock.json
+yarn.lock
+coverage/
+.idea/
+run/
+.DS_Store
+*.sw*
+*.un~
+typings/
+.nyc_output/

+ 12 - 0
service-gateway/.travis.yml

@@ -0,0 +1,12 @@
+
+language: node_js
+node_js:
+  - '10'
+before_install:
+  - npm i npminstall -g
+install:
+  - npminstall
+script:
+  - npm run ci
+after_script:
+  - npminstall codecov && codecov

+ 33 - 0
service-gateway/README.md

@@ -0,0 +1,33 @@
+# service-gateway
+
+
+
+## QuickStart
+
+<!-- add docs here for user -->
+
+see [egg docs][egg] for more detail.
+
+### Development
+
+```bash
+$ npm i
+$ npm run dev
+$ open http://localhost:7001/
+```
+
+### Deploy
+
+```bash
+$ npm start
+$ npm stop
+```
+
+### npm scripts
+
+- Use `npm run lint` to check code style.
+- Use `npm test` to run unit test.
+- Use `npm run autod` to auto detect dependencies upgrade, see [autod](https://www.npmjs.com/package/autod) for more detail.
+
+
+[egg]: https://eggjs.org

+ 142 - 0
service-gateway/app/controller/home.js

@@ -0,0 +1,142 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+const jsonwebtoken = require('jsonwebtoken');
+class HomeController extends Controller {
+  async index() {
+    const { modules } = this.app.config;
+    // 路径参数
+    const { agent, service, module, method, item } = this.ctx.params;
+    // 请求地址
+    const address = modules[service];
+    // 请求方法
+    const requestMethod = this.ctx.request.method;
+    // 请求路径
+    const path = this.ctx.path;
+    let msg = null;
+    let details = null;
+    let result = null;
+    // jwt 验证
+    const auth = await this.auth({ service, path });
+    // 验证失败
+    if (auth.errcode !== 0) {
+      this.ctx.status = 401;
+      this.ctx.body = { errcode: 401, errmsg: '身份验证失败', details: auth.details };
+      return false;
+    }
+    // 发送的数据
+    let data = requestMethod === 'GET' ? this.ctx.query : this.ctx.request.body;
+    if (requestMethod === 'DELETE') data = this.ctx.params.item;
+    // 发送请求
+    const res = await this.ctx.curl(`${address}${path}`, {
+      method: requestMethod,
+      data,
+      nestedQuerystring: true,
+    });
+    // 默认返回值
+    msg = res.data;
+
+    // 日志详情默认值
+    details = data;
+    result = '成功';
+
+    // 错误异常处理(返回值)
+    // 缺少字段检测返回asser
+    if (res.status === 500 && res.data.name === 'AssertionError') {
+      msg = { errcode: -1002, errmsg: res.data.message, data: '' };
+      details = res.data.message;
+      result = '失败';
+    }
+    // 异常抛出检测
+    if (res.status === 500 && (res.data.name === 'ValidationError' || res.data.name === 'CastError')) {
+      msg = { errcode: -1002, errmsg: '系统错误', details: res.data.message };
+      details = res.data.message;
+      result = '失败';
+    }
+    await this.setLog({ agent, service, module, method, item, details: JSON.stringify(details), result, auth });
+    // 默认返回状态 = 当前请求返回状态
+    this.ctx.response.type = res.headers['content-type'];
+    this.ctx.status = res.status;
+    this.ctx.body = msg;
+  }
+
+  // 日志记录
+  async setLog({ agent, service, module, method, item, details, result, auth }) {
+    // 配置
+    const { modules, apipath } = this.app.config;
+    // 请求路径
+    const path = this.ctx.path;
+    // 根据service类型 获取配置文件
+    const logmodules = apipath[service];
+    // 没有配置文件默认放过
+    if (logmodules) {
+      // const items = logmodules.find(e => e.url.includes(path));
+      const items = await this.rewrite_path(logmodules, path);
+      if (items && items.log) {
+        // 此处开始记录日志
+        let userName = null;
+        let name = null;
+        if (auth.decode) {
+          userName = auth.decode.userName;
+          name = auth.decode.name;
+        }
+        try {
+          await this.ctx.curl(`${modules.log}/api/log/log/create`, {
+            method: 'POST',
+            dataType: 'json',
+            data: { agent, service, module, method, item, details, result, userName, name },
+          });
+        } catch (error) {
+          this.ctx.logger.error(`日志添加失败: ${error}`);
+        }
+      }
+    }
+  }
+
+  // 验证函数
+  async auth({ service, path }) {
+    const { jwt, apipath } = this.app.config;
+    // 根据service类型 获取配置文件
+    const modules = apipath[service];
+    // 没有配置文件默认放过
+    if (!modules) return { errcode: 0, details: '' };
+    // 获取与当前路径匹配的项
+    // const item = modules.filter(e => e.url.includes(path));
+    const item = await this.rewrite_path(modules, path);
+    // 没有匹配数据  默认放过
+    if (item) return { errcode: 0, details: '' };
+    // 不验证jwt放过
+    if (!item.jwt) return { errcode: 0, details: '' };
+    // 获取token
+    const token = this.ctx.header.authorization.split('Bearer ')[1];
+    try {
+      // 解密jwt
+      const decode = jsonwebtoken.verify(token, jwt.secret);
+      // 如果有验证签发者
+      if (item && item.issuer) {
+        // 比对签发者
+        if (!item.issuer.includes(decode.iss)) return { errcode: -4001, details: 'issuer fail verification' };
+      }
+      return { errcode: 0, details: '', decode };
+    } catch (error) {
+      return { errcode: -4001, details: error.message };
+    }
+  }
+  // 重写路径
+  async rewrite_path(modules, path) {
+    return modules.find(e => {
+      const { url } = e;
+      let data = null;
+      const urlList = url.split('/');
+      const pathIist = path.split('/');
+      const urlItem = urlList.findIndex(j => j.includes(':'));
+      if (urlItem > 0) data = pathIist[urlItem];
+      if (data !== null) urlList[urlItem] = data;
+      const pathItem = urlList.join('/');
+      if (pathItem === path) return e;
+      return false;
+    });
+  }
+}
+
+module.exports = HomeController;

+ 12 - 0
service-gateway/app/router.js

@@ -0,0 +1,12 @@
+'use strict';
+
+/**
+ * @param {Egg.Application} app - egg application
+ */
+module.exports = app => {
+  const { router, controller } = app;
+  // router.post('/rewritepath', controller.home.rewrite_path);
+  router.get('/:agent/:service/:module/:method', controller.home.index);
+  router.post('/:agent/:service/:module/:method', controller.home.index);
+  router.delete('/:agent/:service/:module/:method/:item', controller.home.index);
+};

+ 14 - 0
service-gateway/appveyor.yml

@@ -0,0 +1,14 @@
+environment:
+  matrix:
+    - nodejs_version: '10'
+
+install:
+  - ps: Install-Product node $env:nodejs_version
+  - npm i npminstall && node_modules\.bin\npminstall
+
+test_script:
+  - node --version
+  - npm --version
+  - npm run test
+
+build: off

+ 197 - 0
service-gateway/config/cms.js

@@ -0,0 +1,197 @@
+'use strict';
+
+module.exports = [
+  // 栏目
+  {
+    url: '/api/cms/column/create',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/column/update',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/column/delete/:id',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/column/query',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  // 内容
+  {
+    url: '/api/cms/contents/create',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/contents/update',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/contents/delete/:id',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/contents/query',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/contents/fetch',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  // 图片新闻类型
+  {
+    url: '/api/cms/imgtype/create',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/imgtype/update',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/imgtype/delete/:id',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/imgtype/query',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  // 图片新闻
+  {
+    url: '/api/cms/imgnews/create',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/imgnews/update',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/imgnews/delete/:id',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/imgnews/query',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/contents/fetch',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  // 菜单
+  {
+    url: '/api/cms/menus/create',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/menus/update',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/menus/delete/:id',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/menus/query',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  // 单页
+  {
+    url: '/api/cms/pages/create',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/pages/update',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/pages/delete/:id',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/pages/query',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/pages/fetch',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  // 配置
+  {
+    url: '/api/cms/toconfig/create',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/toconfig/update',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/toconfig/delete/:id',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/cms/toconfig/query',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+];

+ 54 - 0
service-gateway/config/code.js

@@ -0,0 +1,54 @@
+'use strict';
+
+module.exports = [
+  // 字典类型
+  {
+    url: '/api/code/type/create',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/code/type/update',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/code/type/delete/:id',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/code/type/query',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: false,
+  },
+  // 字典
+  {
+    url: '/api/code/dictionary/create',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/code/dictionary/update',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/code/dictionary/delete/:id',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/code/dictionary/query',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: false,
+  },
+];

+ 60 - 0
service-gateway/config/config.default.js

@@ -0,0 +1,60 @@
+/* eslint valid-jsdoc: "off" */
+
+'use strict';
+const code = require('./code');
+const files = require('./files');
+const cms = require('./cms');
+const log = require('./log');
+const login = require('./login');
+const wx = require('./wx');
+const naf = require('./naf');
+/**
+ * @param {Egg.EggAppInfo} appInfo app info
+ */
+module.exports = appInfo => {
+  /**
+   * built-in config
+   * @type {Egg.EggAppConfig}
+   **/
+  const config = exports = {};
+
+  // use for cookie sign key, should change to your own and keep security
+  config.keys = appInfo.name + '_1637282221255_6501';
+
+  // add your middleware config here
+  config.middleware = [];
+
+  // add your user config here
+  const userConfig = {
+    // myAppName: 'egg',
+  };
+  // 安全配置
+  config.security = {
+    csrf: {
+      // ignoreJSON: true, // 默认为 false,当设置为 true 时,将会放过所有 content-type 为 `application/json` 的请求
+      enable: false,
+    },
+  };
+  config.cluster = {
+    listen: {
+      port: 18090,
+    },
+  };
+  config.modules = {
+    login: 'http://127.0.0.1:9000',
+    code: 'http://127.0.0.1:9001',
+    files: 'http://127.0.0.1:9002',
+    naf: 'http://127.0.0.1:9003',
+    cms: 'http://127.0.0.1:9004',
+    wx: 'http://127.0.0.1:9005',
+    log: 'http://127.0.0.1:9006',
+  };
+  config.jwt = {
+    secret: '123456',
+  };
+  config.apipath = { code, files, naf, cms, login, wx, log };
+  return {
+    ...config,
+    ...userConfig,
+  };
+};

+ 22 - 0
service-gateway/config/files.js

@@ -0,0 +1,22 @@
+'use strict';
+
+module.exports = [
+  {
+    url: '/api/files/:app/upload',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/files/filestore/delete',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/files/filestore/query',
+    jwt: true,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+];

+ 34 - 0
service-gateway/config/log.js

@@ -0,0 +1,34 @@
+'use strict';
+
+module.exports = [
+  {
+    url: '/api/log/log/create',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/log/log/update',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/log/log/delete/:id',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/log/log/query',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/log/log/fetch/:id',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+];

+ 46 - 0
service-gateway/config/login.js

@@ -0,0 +1,46 @@
+'use strict';
+
+module.exports = [
+  // 获取验证码
+  {
+    url: '/api/login/pwdlogin/get_verification_code',
+    jwt: false,
+    issuer: [],
+    log: false,
+  },
+  // 帐号密码登录
+  {
+    url: '/api/login/pwdlogin/auth',
+    jwt: false,
+    issuer: [],
+    log: true,
+  },
+  // 获取二维码(uuid)
+  {
+    url: '/api/login/qrlogin/qrcode',
+    jwt: false,
+    issuer: [],
+    log: false,
+  },
+  // 使用二维码换取登录凭证
+  {
+    url: '/api/login/qrlogin/qrcodeLogin',
+    jwt: false,
+    issuer: [],
+    log: false,
+  },
+  // 获取openid 带参数二维码uuid
+  {
+    url: '/api/login/qrlogin/get_openid',
+    jwt: false,
+    issuer: [],
+    log: false,
+  },
+  // 二维码登录验证
+  {
+    url: '/api/login/qrlogin/auth',
+    jwt: false,
+    issuer: [],
+    log: false,
+  },
+];

+ 147 - 0
service-gateway/config/naf.js

@@ -0,0 +1,147 @@
+'use strict';
+
+module.exports = [
+  // 用户
+  {
+    url: '/api/naf/adminUser/create',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/naf/adminUser/update',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/naf/adminUser/delete/:id',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/naf/adminUser/query',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/naf/adminUser/updatePwd',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  // 角色
+  {
+    url: '/api/naf/role/create',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/naf/role/update',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/naf/role/delete/:id',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/naf/role/query',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  // 菜单
+  {
+    url: '/api/naf/adminMenu/queryUserMenu',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/naf/adminMenu/query',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  // 用户角色
+  {
+    url: '/api/naf/userBindRole/bind',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/naf/userBindRole/unbind',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/naf/userBindRole/queryBind',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/naf/userBindRole/queryRole',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/naf/userBindRole/batchBind',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/naf/userBindRole/batchUnBind',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  // 角色菜单
+  {
+    url: '/api/naf/roleBindMenu/bind',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/naf/roleBindMenu/unbind',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/naf/roleBindMenu/queryBind',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/naf/roleBindMenu/queryRole',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/naf/roleBindMenu/batchBind',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+  {
+    url: '/api/naf/roleBindMenu/batchUnBind',
+    jwt: false,
+    issuer: [ 'naf' ],
+    log: true,
+  },
+];

+ 9 - 0
service-gateway/config/plugin.js

@@ -0,0 +1,9 @@
+'use strict';
+
+/** @type Egg.EggPlugin */
+module.exports = {
+  // had enabled by egg
+  // static: {
+  //   enable: true,
+  // }
+};

+ 48 - 0
service-gateway/config/wx.js

@@ -0,0 +1,48 @@
+'use strict';
+
+module.exports = [
+  // 微信api
+  {
+    url: '/api/wx/wxapi/get_openid',
+    jwt: false,
+    issuer: [],
+    log: false,
+  },
+  {
+    url: '/api/wx/wxapi/get_userInfo',
+    jwt: false,
+    issuer: [],
+    log: false,
+  },
+  {
+    url: '/api/wx/wxapi/pushMould',
+    jwt: true,
+    issuer: [ 'naf', 'user' ],
+    log: true,
+  },
+  // 支付api
+  {
+    url: '/api/wx/payapi/book_order',
+    jwt: true,
+    issuer: [ 'user' ],
+    log: true,
+  },
+  {
+    url: '/api/wx/payapi/pay',
+    jwt: true,
+    issuer: [ 'user' ],
+    log: true,
+  },
+  {
+    url: '/api/wx/payapi/orderClose',
+    jwt: true,
+    issuer: [ 'naf', 'user' ],
+    log: true,
+  },
+  {
+    url: '/api/wx/payapi/refund',
+    jwt: true,
+    issuer: [ 'user' ],
+    log: true,
+  },
+];

+ 17 - 0
service-gateway/ecosystem.config.js

@@ -0,0 +1,17 @@
+'use strict';
+
+const app = 'service-gateway';
+module.exports = {
+  apps: [{
+    name: app, // 应用名称
+    script: './server.js', // 实际启动脚本
+    out: `./logs/${app}.log`,
+    error: `./logs/${app}.err`,
+    watch: [ // 监控变化的目录,一旦变化,自动重启
+      'app', 'config',
+    ],
+    env: {
+      NODE_ENV: process.env.NODE_ENV || 'production', // 环境参数,当前指定为生产环境
+    },
+  }],
+};

+ 5 - 0
service-gateway/jsconfig.json

@@ -0,0 +1,5 @@
+{
+  "include": [
+    "**/*"
+  ]
+}

+ 47 - 0
service-gateway/package.json

@@ -0,0 +1,47 @@
+{
+  "name": "service-gateway",
+  "version": "1.0.0",
+  "description": "",
+  "private": true,
+  "egg": {
+    "declarations": true
+  },
+  "dependencies": {
+    "egg": "^2.15.1",
+    "egg-scripts": "^2.11.0",
+    "jsonwebtoken": "^8.5.1"
+  },
+  "devDependencies": {
+    "autod": "^3.0.1",
+    "autod-egg": "^1.1.0",
+    "egg-bin": "^4.11.0",
+    "egg-ci": "^1.11.0",
+    "egg-mock": "^3.21.0",
+    "eslint": "^5.13.0",
+    "eslint-config-egg": "^7.1.0"
+  },
+  "engines": {
+    "node": ">=10.0.0"
+  },
+  "scripts": {
+    "start": "egg-scripts start --daemon --title=egg-server-service-gateway",
+    "stop": "egg-scripts stop --title=egg-server-service-gateway",
+    "dev": "egg-bin dev",
+    "debug": "egg-bin debug",
+    "test": "npm run lint -- --fix && npm run test-local",
+    "test-local": "egg-bin test",
+    "cov": "egg-bin cov",
+    "lint": "eslint .",
+    "ci": "npm run lint && npm run cov",
+    "autod": "autod"
+  },
+  "ci": {
+    "version": "10"
+  },
+  "repository": {
+    "type": "git",
+    "url": ""
+  },
+  "author": "",
+  "license": "MIT"
+}

+ 0 - 0
service-gateway/server.js


部分文件因文件數量過多而無法顯示