├── .editorconfig ├── .env.development ├── .env.production ├── .env.staging ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── babel.config.js ├── build └── index.js ├── dbs └── koa │ ├── buttons.bson │ ├── buttons.metadata.json │ ├── permissions.bson │ ├── permissions.metadata.json │ ├── roles.bson │ ├── roles.metadata.json │ ├── users.bson │ └── users.metadata.json ├── jest.config.js ├── mock ├── button.js ├── index.js ├── mock-server.js ├── permission.js ├── role.js └── user.js ├── package.json ├── plop-templates ├── component │ ├── index.hbs │ └── prompt.js ├── utils.js └── view │ ├── index.hbs │ └── prompt.js ├── plopfile.js ├── postcss.config.js ├── public ├── favicon.ico └── index.html ├── server ├── .babelrc ├── app.js ├── app │ ├── controller │ │ ├── button.js │ │ ├── permission.js │ │ ├── role.js │ │ ├── user.js │ │ └── utils │ │ │ ├── axios.js │ │ │ └── passport.js │ └── dbs │ │ ├── config.js │ │ └── models │ │ ├── button.js │ │ ├── permission.js │ │ ├── roles.js │ │ └── users.js ├── bin │ └── www ├── package.json ├── public │ └── stylesheets │ │ └── style.css ├── routes │ ├── common.js │ ├── index.js │ └── models │ │ ├── button.js │ │ ├── permission.js │ │ ├── role.js │ │ └── users.js └── views │ ├── error.ejs │ └── index.ejs ├── src ├── App.vue ├── api │ ├── article.js │ ├── qiniu.js │ ├── remote-search.js │ ├── role.js │ ├── system.js │ └── user.js ├── assets │ ├── 401_images │ │ └── 401.gif │ ├── 404_images │ │ ├── 404.png │ │ └── 404_cloud.png │ └── custom-theme │ │ ├── fonts │ │ ├── element-icons.ttf │ │ └── element-icons.woff │ │ └── index.css ├── components │ ├── BackToTop │ │ └── index.vue │ ├── Breadcrumb │ │ └── index.vue │ ├── Charts │ │ ├── Keyboard.vue │ │ ├── LineMarker.vue │ │ ├── MixChart.vue │ │ └── mixins │ │ │ └── resize.js │ ├── DndList │ │ └── index.vue │ ├── DragSelect │ │ └── index.vue │ ├── Dropzone │ │ └── index.vue │ ├── ErrorLog │ │ └── index.vue │ ├── GithubCorner │ │ └── index.vue │ ├── Hamburger │ │ └── index.vue │ ├── HeaderSearch │ │ └── index.vue │ ├── ImageCropper │ │ ├── index.vue │ │ └── utils │ │ │ ├── data2blob.js │ │ │ ├── effectRipple.js │ │ │ ├── language.js │ │ │ └── mimes.js │ ├── JsonEditor │ │ └── index.vue │ ├── Kanban │ │ └── index.vue │ ├── MDinput │ │ └── index.vue │ ├── MarkdownEditor │ │ ├── default-options.js │ │ └── index.vue │ ├── Pagination │ │ └── index.vue │ ├── PanThumb │ │ └── index.vue │ ├── RightPanel │ │ └── index.vue │ ├── Screenfull │ │ └── index.vue │ ├── Share │ │ └── DropdownMenu.vue │ ├── SizeSelect │ │ └── index.vue │ ├── Sticky │ │ └── index.vue │ ├── SvgIcon │ │ └── index.vue │ ├── TextHoverEffect │ │ └── Mallki.vue │ ├── ThemePicker │ │ └── index.vue │ ├── Tinymce │ │ ├── components │ │ │ └── EditorImage.vue │ │ ├── dynamicLoadScript.js │ │ ├── index.vue │ │ ├── plugins.js │ │ └── toolbar.js │ ├── Upload │ │ ├── SingleImage.vue │ │ ├── SingleImage2.vue │ │ └── SingleImage3.vue │ └── UploadExcel │ │ └── index.vue ├── directive │ ├── clipboard │ │ ├── clipboard.js │ │ └── index.js │ ├── el-drag-dialog │ │ ├── drag.js │ │ └── index.js │ ├── el-table │ │ ├── adaptive.js │ │ └── index.js │ ├── permission │ │ ├── index.js │ │ └── permission.js │ ├── sticky.js │ └── waves │ │ ├── index.js │ │ ├── waves.css │ │ └── waves.js ├── filters │ └── index.js ├── icons │ ├── index.js │ ├── svg │ │ ├── 404.svg │ │ ├── bug.svg │ │ ├── chart.svg │ │ ├── clipboard.svg │ │ ├── component.svg │ │ ├── dashboard.svg │ │ ├── documentation.svg │ │ ├── drag.svg │ │ ├── edit.svg │ │ ├── education.svg │ │ ├── email.svg │ │ ├── example.svg │ │ ├── excel.svg │ │ ├── exit-fullscreen.svg │ │ ├── eye-open.svg │ │ ├── eye.svg │ │ ├── form.svg │ │ ├── fullscreen.svg │ │ ├── guide.svg │ │ ├── icon.svg │ │ ├── international.svg │ │ ├── language.svg │ │ ├── link.svg │ │ ├── list.svg │ │ ├── lock.svg │ │ ├── message.svg │ │ ├── money.svg │ │ ├── nested.svg │ │ ├── password.svg │ │ ├── pdf.svg │ │ ├── people.svg │ │ ├── peoples.svg │ │ ├── qq.svg │ │ ├── search.svg │ │ ├── shopping.svg │ │ ├── size.svg │ │ ├── skill.svg │ │ ├── star.svg │ │ ├── tab.svg │ │ ├── table.svg │ │ ├── theme.svg │ │ ├── tree-table.svg │ │ ├── tree.svg │ │ ├── user.svg │ │ ├── wechat.svg │ │ └── zip.svg │ └── svgo.yml ├── layout │ ├── components │ │ ├── AppMain.vue │ │ ├── Navbar.vue │ │ ├── Settings │ │ │ └── index.vue │ │ ├── Sidebar │ │ │ ├── FixiOSBug.js │ │ │ ├── Item.vue │ │ │ ├── Link.vue │ │ │ ├── Logo.vue │ │ │ ├── SidebarItem.vue │ │ │ └── index.vue │ │ ├── TagsView │ │ │ ├── ScrollPane.vue │ │ │ └── index.vue │ │ └── index.js │ ├── index.vue │ └── mixin │ │ └── ResizeHandler.js ├── main.js ├── permission.js ├── router │ ├── index.js │ └── modules │ │ ├── charts.js │ │ ├── components.js │ │ ├── nested.js │ │ └── table.js ├── settings.js ├── store │ ├── getters.js │ ├── index.js │ └── modules │ │ ├── app.js │ │ ├── errorLog.js │ │ ├── permission.js │ │ ├── settings.js │ │ ├── tagsView.js │ │ └── user.js ├── styles │ ├── btn.scss │ ├── element-ui.scss │ ├── element-variables.scss │ ├── index.scss │ ├── mixin.scss │ ├── sidebar.scss │ ├── transition.scss │ └── variables.scss ├── utils │ ├── auth.js │ ├── clipboard.js │ ├── dict.js │ ├── error-log.js │ ├── get-page-title.js │ ├── index.js │ ├── open-window.js │ ├── permission.js │ ├── request.js │ ├── scroll-to.js │ └── validate.js ├── vendor │ ├── Export2Excel.js │ └── Export2Zip.js └── views │ ├── dashboard │ ├── admin │ │ ├── components │ │ │ ├── BarChart.vue │ │ │ ├── BoxCard.vue │ │ │ ├── LineChart.vue │ │ │ ├── PanelGroup.vue │ │ │ ├── PieChart.vue │ │ │ ├── RaddarChart.vue │ │ │ ├── TodoList │ │ │ │ ├── Todo.vue │ │ │ │ ├── index.scss │ │ │ │ └── index.vue │ │ │ ├── TransactionTable.vue │ │ │ └── mixins │ │ │ │ └── resize.js │ │ └── index.vue │ ├── editor │ │ └── index.vue │ └── index.vue │ ├── error-log │ ├── components │ │ ├── ErrorTestA.vue │ │ └── ErrorTestB.vue │ └── index.vue │ ├── error-page │ ├── 401.vue │ └── 404.vue │ ├── example │ ├── charts │ │ ├── keyboard.vue │ │ ├── line.vue │ │ └── mix-chart.vue │ ├── clipboard │ │ └── index.vue │ ├── components-demo │ │ ├── avatar-upload.vue │ │ ├── back-to-top.vue │ │ ├── count-to.vue │ │ ├── dnd-list.vue │ │ ├── drag-dialog.vue │ │ ├── drag-kanban.vue │ │ ├── drag-select.vue │ │ ├── dropzone.vue │ │ ├── json-editor.vue │ │ ├── markdown.vue │ │ ├── mixin.vue │ │ ├── split-pane.vue │ │ ├── sticky.vue │ │ └── tinymce.vue │ ├── documentation │ │ └── index.vue │ ├── example │ │ ├── components │ │ │ ├── ArticleDetail.vue │ │ │ ├── Dropdown │ │ │ │ ├── Comment.vue │ │ │ │ ├── Platform.vue │ │ │ │ ├── SourceUrl.vue │ │ │ │ └── index.js │ │ │ └── Warning.vue │ │ ├── create.vue │ │ ├── edit.vue │ │ └── list.vue │ ├── excel │ │ ├── components │ │ │ ├── AutoWidthOption.vue │ │ │ ├── BookTypeOption.vue │ │ │ └── FilenameOption.vue │ │ ├── export-excel.vue │ │ ├── merge-header.vue │ │ ├── select-excel.vue │ │ └── upload-excel.vue │ ├── guide │ │ ├── index.vue │ │ └── steps.js │ ├── icons │ │ ├── element-icons.js │ │ ├── index.vue │ │ └── svg-icons.js │ ├── nested │ │ ├── menu1 │ │ │ ├── index.vue │ │ │ ├── menu1-1 │ │ │ │ └── index.vue │ │ │ ├── menu1-2 │ │ │ │ ├── index.vue │ │ │ │ ├── menu1-2-1 │ │ │ │ │ └── index.vue │ │ │ │ └── menu1-2-2 │ │ │ │ │ └── index.vue │ │ │ └── menu1-3 │ │ │ │ └── index.vue │ │ └── menu2 │ │ │ └── index.vue │ ├── pdf │ │ ├── content.js │ │ ├── download.vue │ │ └── index.vue │ ├── permission │ │ ├── components │ │ │ └── SwitchRoles.vue │ │ ├── directive.vue │ │ ├── page.vue │ │ └── role.vue │ ├── profile │ │ ├── components │ │ │ ├── Account.vue │ │ │ ├── Activity.vue │ │ │ ├── Timeline.vue │ │ │ └── UserCard.vue │ │ └── index.vue │ ├── qiniu │ │ └── upload.vue │ ├── tab │ │ ├── components │ │ │ └── TabPane.vue │ │ └── index.vue │ ├── table │ │ ├── complex-table.vue │ │ ├── drag-table.vue │ │ ├── dynamic-table │ │ │ ├── components │ │ │ │ ├── FixedThead.vue │ │ │ │ └── UnfixedThead.vue │ │ │ └── index.vue │ │ └── inline-edit-table.vue │ ├── theme │ │ └── index.vue │ └── zip │ │ └── index.vue │ ├── login │ ├── auth-redirect.vue │ ├── components │ │ └── SocialSignin.vue │ └── index.vue │ ├── redirect │ └── index.vue │ ├── system │ ├── button.vue │ ├── permission.vue │ ├── role.vue │ └── user.vue │ └── test │ └── test.vue ├── tests └── unit │ ├── .eslintrc.js │ ├── components │ ├── Hamburger.spec.js │ └── SvgIcon.spec.js │ └── utils │ ├── formatTime.spec.js │ ├── parseTime.spec.js │ └── validate.spec.js └── vue.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | end_of_line = lf 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [*.md] 13 | insert_final_newline = false 14 | trim_trailing_whitespace = false 15 | -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | # just a flag 2 | ENV = 'development' 3 | 4 | # base api 5 | VUE_APP_BASE_API = '/dev-api' 6 | 7 | # vue-cli uses the VUE_CLI_BABEL_TRANSPILE_MODULES environment variable, 8 | # to control whether the babel-plugin-dynamic-import-node plugin is enabled. 9 | # It only does one thing by converting all import() to require(). 10 | # This configuration can significantly increase the speed of hot updates, 11 | # when you have a large number of pages. 12 | # Detail: https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/babel-preset-app/index.js 13 | 14 | VUE_CLI_BABEL_TRANSPILE_MODULES = true 15 | -------------------------------------------------------------------------------- /.env.production: -------------------------------------------------------------------------------- 1 | # just a flag 2 | ENV = 'production' 3 | 4 | # base api 5 | VUE_APP_BASE_API = '/prod-api' 6 | 7 | -------------------------------------------------------------------------------- /.env.staging: -------------------------------------------------------------------------------- 1 | NODE_ENV = production 2 | 3 | # just a flag 4 | ENV = 'staging' 5 | 6 | # base api 7 | VUE_APP_BASE_API = '/stage-api' 8 | 9 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | build/*.js 2 | src/assets 3 | public 4 | dist 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | **/*.log 8 | 9 | tests/**/coverage/ 10 | tests/e2e/reports 11 | selenium-debug.log 12 | 13 | # Editor directories and files 14 | .idea 15 | .vscode 16 | *.suo 17 | *.ntvs* 18 | *.njsproj 19 | *.sln 20 | *.local 21 | 22 | package-lock.json 23 | yarn.lock 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 10 3 | script: npm run test 4 | notifications: 5 | email: false 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-present PanJiaChen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /build/index.js: -------------------------------------------------------------------------------- 1 | const { run } = require('runjs') 2 | const chalk = require('chalk') 3 | const config = require('../vue.config.js') 4 | const rawArgv = process.argv.slice(2) 5 | const args = rawArgv.join(' ') 6 | 7 | if (process.env.npm_config_preview || rawArgv.includes('--preview')) { 8 | const report = rawArgv.includes('--report') 9 | 10 | run(`vue-cli-service build ${args}`) 11 | 12 | const port = 9526 13 | const publicPath = config.publicPath 14 | 15 | var connect = require('connect') 16 | var serveStatic = require('serve-static') 17 | const app = connect() 18 | 19 | app.use( 20 | publicPath, 21 | serveStatic('./dist', { 22 | index: ['index.html', '/'] 23 | }) 24 | ) 25 | 26 | app.listen(port, function () { 27 | console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`)) 28 | if (report) { 29 | console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}report.html`)) 30 | } 31 | 32 | }) 33 | } else { 34 | run(`vue-cli-service build ${args}`) 35 | } 36 | -------------------------------------------------------------------------------- /dbs/koa/buttons.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhengLinPing/vue-permission-admin/e1f7f3a59e2487dc6aa70f2dea49f2047e498a75/dbs/koa/buttons.bson -------------------------------------------------------------------------------- /dbs/koa/buttons.metadata.json: -------------------------------------------------------------------------------- 1 | {"options":{},"indexes":[{"v":2,"key":{"_id":1},"name":"_id_","ns":"koa.buttons"}],"uuid":"a90ed41c44bc49fbb686055d3375b40e"} -------------------------------------------------------------------------------- /dbs/koa/permissions.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhengLinPing/vue-permission-admin/e1f7f3a59e2487dc6aa70f2dea49f2047e498a75/dbs/koa/permissions.bson -------------------------------------------------------------------------------- /dbs/koa/permissions.metadata.json: -------------------------------------------------------------------------------- 1 | {"options":{},"indexes":[{"v":2,"key":{"_id":1},"name":"_id_","ns":"koa.permissions"}],"uuid":"bc8ccde296184ac49996069d1547be33"} -------------------------------------------------------------------------------- /dbs/koa/roles.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhengLinPing/vue-permission-admin/e1f7f3a59e2487dc6aa70f2dea49f2047e498a75/dbs/koa/roles.bson -------------------------------------------------------------------------------- /dbs/koa/roles.metadata.json: -------------------------------------------------------------------------------- 1 | {"options":{},"indexes":[{"v":2,"key":{"_id":1},"name":"_id_","ns":"koa.roles"}],"uuid":"8dc1255b94a8474cadee05cb50258a74"} -------------------------------------------------------------------------------- /dbs/koa/users.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhengLinPing/vue-permission-admin/e1f7f3a59e2487dc6aa70f2dea49f2047e498a75/dbs/koa/users.bson -------------------------------------------------------------------------------- /dbs/koa/users.metadata.json: -------------------------------------------------------------------------------- 1 | {"options":{},"indexes":[{"v":2,"key":{"_id":1},"name":"_id_","ns":"koa.users"},{"v":2,"unique":true,"key":{"username":1},"name":"username_1","ns":"koa.users","background":true}],"uuid":"03b2d4df712047dd83dee6e849a3a05e"} -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleFileExtensions: ['js', 'jsx', 'json', 'vue'], 3 | transform: { 4 | '^.+\\.vue$': 'vue-jest', 5 | '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 6 | 'jest-transform-stub', 7 | '^.+\\.jsx?$': 'babel-jest' 8 | }, 9 | moduleNameMapper: { 10 | '^@/(.*)$': '/src/$1' 11 | }, 12 | snapshotSerializers: ['jest-serializer-vue'], 13 | testMatch: [ 14 | '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)' 15 | ], 16 | collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'], 17 | coverageDirectory: '/tests/unit/coverage', 18 | // 'collectCoverage': true, 19 | 'coverageReporters': [ 20 | 'lcov', 21 | 'text-summary' 22 | ], 23 | testURL: 'http://localhost/' 24 | } 25 | -------------------------------------------------------------------------------- /mock/index.js: -------------------------------------------------------------------------------- 1 | import Mock from 'mockjs' 2 | import { param2Obj } from '../src/utils' 3 | 4 | import user from './user' 5 | import role from './role' 6 | import permission from './permission' 7 | import button from './button' 8 | 9 | 10 | const mocks = [ 11 | ...user, 12 | ...role, 13 | ...button, 14 | ...permission 15 | 16 | ] 17 | 18 | // for front mock 19 | // please use it cautiously, it will redefine XMLHttpRequest, 20 | // which will cause many of your third-party libraries to be invalidated(like progress event). 21 | export function mockXHR() { 22 | // mock patch 23 | // https://github.com/nuysoft/Mock/issues/300 24 | Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send 25 | Mock.XHR.prototype.send = function() { 26 | if (this.custom.xhr) { 27 | this.custom.xhr.withCredentials = this.withCredentials || false 28 | 29 | if (this.responseType) { 30 | this.custom.xhr.responseType = this.responseType 31 | } 32 | } 33 | this.proxy_send(...arguments) 34 | } 35 | 36 | function XHR2ExpressReqWrap(respond) { 37 | return function(options) { 38 | let result = null 39 | if (respond instanceof Function) { 40 | const { body, type, url } = options 41 | // https://expressjs.com/en/4x/api.html#req 42 | result = respond({ 43 | method: type, 44 | body: JSON.parse(body), 45 | query: param2Obj(url) 46 | }) 47 | } else { 48 | result = respond 49 | } 50 | return Mock.mock(result) 51 | } 52 | } 53 | 54 | for (const i of mocks) { 55 | Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response)) 56 | } 57 | } 58 | 59 | // for mock server 60 | const responseFake = (url, type, respond) => { 61 | return { 62 | url: new RegExp(`/mock${url}`), 63 | type: type || 'get', 64 | response(req, res) { 65 | res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond)) 66 | } 67 | } 68 | } 69 | 70 | export default mocks.map(route => { 71 | return responseFake(route.url, route.type, route.response) 72 | }) 73 | -------------------------------------------------------------------------------- /mock/mock-server.js: -------------------------------------------------------------------------------- 1 | const chokidar = require('chokidar') 2 | const bodyParser = require('body-parser') 3 | const chalk = require('chalk') 4 | const path = require('path') 5 | 6 | const mockDir = path.join(process.cwd(), 'mock') 7 | 8 | function registerRoutes(app) { 9 | let mockLastIndex 10 | const { default: mocks } = require('./index.js') 11 | for (const mock of mocks) { 12 | app[mock.type](mock.url, mock.response) 13 | mockLastIndex = app._router.stack.length 14 | } 15 | const mockRoutesLength = Object.keys(mocks).length 16 | return { 17 | mockRoutesLength: mockRoutesLength, 18 | mockStartIndex: mockLastIndex - mockRoutesLength 19 | } 20 | } 21 | 22 | function unregisterRoutes() { 23 | Object.keys(require.cache).forEach(i => { 24 | if (i.includes(mockDir)) { 25 | delete require.cache[require.resolve(i)] 26 | } 27 | }) 28 | } 29 | 30 | module.exports = app => { 31 | // es6 polyfill 32 | require('@babel/register') 33 | 34 | // parse app.body 35 | // https://expressjs.com/en/4x/api.html#req.body 36 | app.use(bodyParser.json()) 37 | app.use(bodyParser.urlencoded({ 38 | extended: true 39 | })) 40 | 41 | const mockRoutes = registerRoutes(app) 42 | var mockRoutesLength = mockRoutes.mockRoutesLength 43 | var mockStartIndex = mockRoutes.mockStartIndex 44 | 45 | // watch files, hot reload mock server 46 | chokidar.watch(mockDir, { 47 | ignored: /mock-server/, 48 | ignoreInitial: true 49 | }).on('all', (event, path) => { 50 | if (event === 'change' || event === 'add') { 51 | try { 52 | // remove mock routes stack 53 | app._router.stack.splice(mockStartIndex, mockRoutesLength) 54 | 55 | // clear routes cache 56 | unregisterRoutes() 57 | 58 | const mockRoutes = registerRoutes(app) 59 | mockRoutesLength = mockRoutes.mockRoutesLength 60 | mockStartIndex = mockRoutes.mockStartIndex 61 | 62 | console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${path}`)) 63 | } catch (error) { 64 | console.log(chalk.redBright(error)) 65 | } 66 | } 67 | }) 68 | } 69 | -------------------------------------------------------------------------------- /plop-templates/component/index.hbs: -------------------------------------------------------------------------------- 1 | {{#if template}} 2 | 5 | {{/if}} 6 | 7 | {{#if script}} 8 | 20 | {{/if}} 21 | 22 | {{#if style}} 23 | 26 | {{/if}} 27 | -------------------------------------------------------------------------------- /plop-templates/component/prompt.js: -------------------------------------------------------------------------------- 1 | const { notEmpty } = require('../utils.js') 2 | 3 | module.exports = { 4 | description: 'generate vue component', 5 | prompts: [{ 6 | type: 'input', 7 | name: 'name', 8 | message: 'component name please', 9 | validate: notEmpty('name') 10 | }, 11 | { 12 | type: 'checkbox', 13 | name: 'blocks', 14 | message: 'Blocks:', 15 | choices: [{ 16 | name: '