lex-xin 3 years ago
commit
d28916383b
17 changed files with 830 additions and 0 deletions
  1. 14 0
      .editorconfig
  2. 14 0
      .env.development
  3. 6 0
      .env.production
  4. 8 0
      .env.staging
  5. 4 0
      .eslintignore
  6. 198 0
      .eslintrc.js
  7. 26 0
      .gitignore
  8. 5 0
      .travis.yml
  9. 19 0
      Dockerfile
  10. 165 0
      LICENSE
  11. 5 0
      babel.config.js
  12. 35 0
      build/index.js
  13. 43 0
      docker/entrypoint.sh
  14. 126 0
      docker/nginx.conf
  15. 24 0
      jest.config.js
  16. 9 0
      jsconfig.json
  17. 129 0
      package.json

+ 14 - 0
.editorconfig

@@ -0,0 +1,14 @@
+# https://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.md]
+insert_final_newline = false
+trim_trailing_whitespace = false

+ 14 - 0
.env.development

@@ -0,0 +1,14 @@
+# just a flag
+ENV = 'development'
+
+# base api
+VUE_APP_BASE_API = 'http://mandev.dayaedu.com/api-oa'
+
+# vue-cli uses the VUE_CLI_BABEL_TRANSPILE_MODULES environment variable,
+# to control whether the babel-plugin-dynamic-import-node plugin is enabled.
+# It only does one thing by converting all import() to require().
+# This configuration can significantly increase the speed of hot updates,
+# when you have a large number of pages.
+# Detail:  https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/babel-preset-app/index.js
+
+VUE_CLI_BABEL_TRANSPILE_MODULES = true

+ 6 - 0
.env.production

@@ -0,0 +1,6 @@
+# just a flag
+ENV = 'production'
+
+# base api
+VUE_APP_BASE_API = 'http://fdevops.com:8001'
+

+ 8 - 0
.env.staging

@@ -0,0 +1,8 @@
+NODE_ENV = production
+
+# just a flag
+ENV = 'staging'
+
+# base api
+VUE_APP_BASE_API = ''
+

+ 4 - 0
.eslintignore

@@ -0,0 +1,4 @@
+build/*.js
+src/assets
+public
+dist

+ 198 - 0
.eslintrc.js

@@ -0,0 +1,198 @@
+module.exports = {
+  root: true,
+  parserOptions: {
+    parser: 'babel-eslint',
+    sourceType: 'module'
+  },
+  env: {
+    browser: true,
+    node: true,
+    es6: true,
+  },
+  extends: ['plugin:vue/recommended', 'eslint:recommended'],
+
+  // add your custom rules here
+  //it is base on https://github.com/vuejs/eslint-config-vue
+  rules: {
+    "vue/max-attributes-per-line": [2, {
+      "singleline": 10,
+      "multiline": {
+        "max": 1,
+        "allowFirstLine": false
+      }
+    }],
+    "vue/singleline-html-element-content-newline": "off",
+    "vue/multiline-html-element-content-newline":"off",
+    "vue/name-property-casing": ["error", "PascalCase"],
+    "vue/no-v-html": "off",
+    'accessor-pairs': 2,
+    'arrow-spacing': [2, {
+      'before': true,
+      'after': true
+    }],
+    'block-spacing': [2, 'always'],
+    'brace-style': [2, '1tbs', {
+      'allowSingleLine': true
+    }],
+    'camelcase': [0, {
+      'properties': 'always'
+    }],
+    'comma-dangle': [2, 'never'],
+    'comma-spacing': [2, {
+      'before': false,
+      'after': true
+    }],
+    'comma-style': [2, 'last'],
+    'constructor-super': 2,
+    'curly': [2, 'multi-line'],
+    'dot-location': [2, 'property'],
+    'eol-last': 2,
+    'eqeqeq': ["error", "always", {"null": "ignore"}],
+    'generator-star-spacing': [2, {
+      'before': true,
+      'after': true
+    }],
+    'handle-callback-err': [2, '^(err|error)$'],
+    'indent': [2, 2, {
+      'SwitchCase': 1
+    }],
+    'jsx-quotes': [2, 'prefer-single'],
+    'key-spacing': [2, {
+      'beforeColon': false,
+      'afterColon': true
+    }],
+    'keyword-spacing': [2, {
+      'before': true,
+      'after': true
+    }],
+    'new-cap': [2, {
+      'newIsCap': true,
+      'capIsNew': false
+    }],
+    'new-parens': 2,
+    'no-array-constructor': 2,
+    'no-caller': 2,
+    'no-console': 'off',
+    'no-class-assign': 2,
+    'no-cond-assign': 2,
+    'no-const-assign': 2,
+    'no-control-regex': 0,
+    'no-delete-var': 2,
+    'no-dupe-args': 2,
+    'no-dupe-class-members': 2,
+    'no-dupe-keys': 2,
+    'no-duplicate-case': 2,
+    'no-empty-character-class': 2,
+    'no-empty-pattern': 2,
+    'no-eval': 2,
+    'no-ex-assign': 2,
+    'no-extend-native': 2,
+    'no-extra-bind': 2,
+    'no-extra-boolean-cast': 2,
+    'no-extra-parens': [2, 'functions'],
+    'no-fallthrough': 2,
+    'no-floating-decimal': 2,
+    'no-func-assign': 2,
+    'no-implied-eval': 2,
+    'no-inner-declarations': [2, 'functions'],
+    'no-invalid-regexp': 2,
+    'no-irregular-whitespace': 2,
+    'no-iterator': 2,
+    'no-label-var': 2,
+    'no-labels': [2, {
+      'allowLoop': false,
+      'allowSwitch': false
+    }],
+    'no-lone-blocks': 2,
+    'no-mixed-spaces-and-tabs': 2,
+    'no-multi-spaces': 2,
+    'no-multi-str': 2,
+    'no-multiple-empty-lines': [2, {
+      'max': 1
+    }],
+    'no-native-reassign': 2,
+    'no-negated-in-lhs': 2,
+    'no-new-object': 2,
+    'no-new-require': 2,
+    'no-new-symbol': 2,
+    'no-new-wrappers': 2,
+    'no-obj-calls': 2,
+    'no-octal': 2,
+    'no-octal-escape': 2,
+    'no-path-concat': 2,
+    'no-proto': 2,
+    'no-redeclare': 2,
+    'no-regex-spaces': 2,
+    'no-return-assign': [2, 'except-parens'],
+    'no-self-assign': 2,
+    'no-self-compare': 2,
+    'no-sequences': 2,
+    'no-shadow-restricted-names': 2,
+    'no-spaced-func': 2,
+    'no-sparse-arrays': 2,
+    'no-this-before-super': 2,
+    'no-throw-literal': 2,
+    'no-trailing-spaces': 2,
+    'no-undef': 2,
+    'no-undef-init': 2,
+    'no-unexpected-multiline': 2,
+    'no-unmodified-loop-condition': 2,
+    'no-unneeded-ternary': [2, {
+      'defaultAssignment': false
+    }],
+    'no-unreachable': 2,
+    'no-unsafe-finally': 2,
+    'no-unused-vars': [2, {
+      'vars': 'all',
+      'args': 'none'
+    }],
+    'no-useless-call': 2,
+    'no-useless-computed-key': 2,
+    'no-useless-constructor': 2,
+    'no-useless-escape': 0,
+    'no-whitespace-before-property': 2,
+    'no-with': 2,
+    'one-var': [2, {
+      'initialized': 'never'
+    }],
+    'operator-linebreak': [2, 'after', {
+      'overrides': {
+        '?': 'before',
+        ':': 'before'
+      }
+    }],
+    'padded-blocks': [2, 'never'],
+    'quotes': [2, 'single', {
+      'avoidEscape': true,
+      'allowTemplateLiterals': true
+    }],
+    'semi': [2, 'never'],
+    'semi-spacing': [2, {
+      'before': false,
+      'after': true
+    }],
+    'space-before-blocks': [2, 'always'],
+    'space-before-function-paren': [2, 'never'],
+    'space-in-parens': [2, 'never'],
+    'space-infix-ops': 2,
+    'space-unary-ops': [2, {
+      'words': true,
+      'nonwords': false
+    }],
+    'spaced-comment': [2, 'always', {
+      'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
+    }],
+    'template-curly-spacing': [2, 'never'],
+    'use-isnan': 2,
+    'valid-typeof': 2,
+    'wrap-iife': [2, 'any'],
+    'yield-star-spacing': [2, 'both'],
+    'yoda': [2, 'never'],
+    'prefer-const': 2,
+    'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
+    'object-curly-spacing': [2, 'always', {
+      objectsInObjects: false
+    }],
+    'array-bracket-spacing': [2, 'never']
+  }
+}

+ 26 - 0
.gitignore

@@ -0,0 +1,26 @@
+.DS_Store
+node_modules/
+dist/
+dist.tar.gz
+web/
+web.tar.gz
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+**/*.log
+
+tests/**/coverage/
+tests/e2e/reports
+selenium-debug.log
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.local
+
+package-lock.json
+yarn.lock

+ 5 - 0
.travis.yml

@@ -0,0 +1,5 @@
+language: node_js
+node_js: 10
+script: npm run test
+notifications:
+  email: false

+ 19 - 0
Dockerfile

@@ -0,0 +1,19 @@
+FROM node:14.15.0 as builder
+
+WORKDIR /opt/ferry_web
+COPY . .
+
+RUN npm install -g cnpm --registry=https://registry.npm.taobao.org && cnpm install
+RUN npm run build:prod
+
+FROM nginx:1.18.0
+
+COPY --from=builder /opt/ferry_web/web /opt/web
+COPY docker/nginx.conf /etc/nginx/nginx.conf
+COPY docker/entrypoint.sh /entrypoint.sh
+
+ENV LISTEN_DOMAIN=fdevops.com
+
+#暴露容器8001端口
+EXPOSE 8001
+ENTRYPOINT [ "/entrypoint.sh" ]

+ 165 - 0
LICENSE

@@ -0,0 +1,165 @@
+                   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.

+ 5 - 0
babel.config.js

@@ -0,0 +1,5 @@
+module.exports = {
+  presets: [
+    '@vue/app'
+  ]
+}

+ 35 - 0
build/index.js

@@ -0,0 +1,35 @@
+const { run } = require('runjs')
+const chalk = require('chalk')
+const config = require('../vue.config.js')
+const rawArgv = process.argv.slice(2)
+const args = rawArgv.join(' ')
+
+if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
+  const report = rawArgv.includes('--report')
+
+  run(`vue-cli-service build ${args}`)
+
+  const port = 9526
+  const publicPath = config.publicPath
+
+  var connect = require('connect')
+  var serveStatic = require('serve-static')
+  const app = connect()
+
+  app.use(
+    publicPath,
+    serveStatic('./dist', {
+      index: ['index.html', '/']
+    })
+  )
+
+  app.listen(port, function () {
+    console.log(chalk.green(`> Preview at  http://localhost:${port}${publicPath}`))
+    if (report) {
+      console.log(chalk.green(`> Report at  http://localhost:${port}${publicPath}report.html`))
+    }
+
+  })
+} else {
+  run(`vue-cli-service build ${args}`)
+}

+ 43 - 0
docker/entrypoint.sh

@@ -0,0 +1,43 @@
+#!/bin/sh
+# vim:sw=4:ts=4:et
+
+grep -r -o "http://fdevops.com:8001" /opt/web |awk -F ':' '{print $1}' | xargs sed -i s"#http://fdevops.com:8001#http://${LISTEN_DOMAIN}:8001#g"
+grep -r -o "VUE_APP_BASE_API" /opt/web |awk -F ':' '{print $1}' | xargs sed -i s"#VUE_APP_BASE_API#http://${LISTEN_DOMAIN}:8001#g"
+grep -r -o "localhost" /opt/web/static/web/js |awk -F ':' '{print $1}' | xargs sed -i s"#localhost#${LISTEN_DOMAIN}#g"
+grep -r -o "fdevops.com" /opt/web/static/web/js |awk -F ':' '{print $1}' | xargs sed -i s"#fdevops.com#${LISTEN_DOMAIN}#g"
+
+set -e
+
+if [ -z "${NGINX_ENTRYPOINT_QUIET_LOGS:-}" ]; then
+    exec 3>&1
+else
+    exec 3>/dev/null
+fi
+
+if [ "$1" = "nginx" -o "$1" = "nginx-debug" ]; then
+    if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then
+        echo >&3 "$0: /docker-entrypoint.d/ is not empty, will attempt to perform configuration"
+
+        echo >&3 "$0: Looking for shell scripts in /docker-entrypoint.d/"
+        find "/docker-entrypoint.d/" -follow -type f -print | sort -n | while read -r f; do
+            case "$f" in
+                *.sh)
+                    if [ -x "$f" ]; then
+                        echo >&3 "$0: Launching $f";
+                        "$f"
+                    else
+                        # warn on shell scripts without exec bit
+                        echo >&3 "$0: Ignoring $f, not executable";
+                    fi
+                    ;;
+                *) echo >&3 "$0: Ignoring $f";;
+            esac
+        done
+
+        echo >&3 "$0: Configuration complete; ready for start up"
+    else
+        echo >&3 "$0: No files found in /docker-entrypoint.d/, skipping configuration"
+    fi
+fi
+
+nginx -g "daemon off;"

+ 126 - 0
docker/nginx.conf

@@ -0,0 +1,126 @@
+user  nginx;
+worker_processes auto;
+
+error_log  /var/log/nginx/error.log warn;
+pid /var/run/nginx.pid;
+worker_rlimit_nofile 51200;
+
+events {
+  use epoll;
+  worker_connections 51200;
+  multi_accept on;
+}
+
+http {
+  include mime.types;
+  default_type application/octet-stream;
+  server_names_hash_bucket_size 128;
+  client_header_buffer_size 32k;
+  large_client_header_buffers 4 32k;
+  client_max_body_size 1024m;
+  client_body_buffer_size 10m;
+  sendfile on;
+  tcp_nopush on;
+  keepalive_timeout 120;
+  server_tokens off;
+  tcp_nodelay on;
+
+  fastcgi_connect_timeout 300;
+  fastcgi_send_timeout 300;
+  fastcgi_read_timeout 300;
+  fastcgi_buffer_size 64k;
+  fastcgi_buffers 4 64k;
+  fastcgi_busy_buffers_size 128k;
+  fastcgi_temp_file_write_size 128k;
+  fastcgi_intercept_errors on;
+
+  #Gzip Compression
+  gzip on;
+  gzip_buffers 16 8k;
+  gzip_comp_level 6;
+  gzip_http_version 1.1;
+  gzip_min_length 256;
+  gzip_proxied any;
+  gzip_vary on;
+  gzip_types
+    text/xml application/xml application/atom+xml application/rss+xml application/xhtml+xml image/svg+xml
+    text/javascript application/javascript application/x-javascript
+    text/x-json application/json application/x-web-app-manifest+json
+    text/css text/plain text/x-component
+    font/opentype application/x-font-ttf application/vnd.ms-fontobject
+    image/x-icon;
+  gzip_disable "MSIE [1-6]\.(?!.*SV1)";
+
+  proxy_ignore_client_abort on;
+
+  server {
+    listen 8001; # 监听端口
+    # server_name -; # 域名可以有多个,用空格隔开
+
+    #charset koi8-r;
+
+    #access_log  logs/host.access.log  main;
+    location / {
+      root /opt/web;
+      index index.html index.htm; #目录内的默认打开文件,如果没有匹配到index.html,则搜索index.htm,依次类推
+    }
+
+    #ssl配置省略
+    location /api {
+      # rewrite ^.+api/?(.*)$ /$1 break;
+      proxy_pass http://ferry_backend:8002; #node api server 即需要代理的IP地址
+        proxy_redirect off;
+      proxy_set_header Host $host:$server_port;
+      proxy_set_header X-Real-IP $remote_addr;
+      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+    }
+
+    # 登陆
+    location /login {
+      proxy_pass http://ferry_backend:8002; #node api server 即需要代理的IP地址
+      proxy_redirect off;
+      proxy_ignore_client_abort on;
+      proxy_max_temp_file_size 256m;
+      proxy_connect_timeout      90;
+      proxy_send_timeout         90;
+      proxy_read_timeout         90;
+      proxy_buffer_size          4k;
+      proxy_buffers              4 32k;
+      proxy_busy_buffers_size    32k;
+      proxy_temp_file_write_size 64k;
+      proxy_http_version 1.1;
+      proxy_set_header Connection "";
+      proxy_set_header Host $host:$server_port;
+      proxy_set_header X-Real-IP $remote_addr;
+      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+    }
+
+    # 刷新token
+    location /refresh_token {
+      proxy_pass http://ferry_backend:8002; #node api server 即需要代理的IP地址
+        proxy_set_header Host $host:$server_port;
+    }
+
+    # 接口地址
+    location /swagger {
+      proxy_pass http://ferry_backend:8002; #node api server 即需要代理的IP地址
+        proxy_set_header Host $host:$server_port;
+    }
+
+    # 后端静态文件路径
+    location /static/uploadfile {
+      proxy_pass http://ferry_backend:8002; #node api server 即需要代理的IP地址
+        proxy_set_header Host $host:$server_port;
+    }
+
+    #error_page  404              /404.html;    #对错误页面404.html 做了定向配置
+
+    # redirect server error pages to the static page /50x.html
+    #将服务器错误页面重定向到静态页面/50x.html
+    #
+    error_page 500 502 503 504 /50x.html;
+    location = /50x.html {
+      root html;
+    }
+  }
+}

+ 24 - 0
jest.config.js

@@ -0,0 +1,24 @@
+module.exports = {
+  moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
+  transform: {
+    '^.+\\.vue$': 'vue-jest',
+    '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
+      'jest-transform-stub',
+    '^.+\\.jsx?$': 'babel-jest'
+  },
+  moduleNameMapper: {
+    '^@/(.*)$': '<rootDir>/src/$1'
+  },
+  snapshotSerializers: ['jest-serializer-vue'],
+  testMatch: [
+    '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
+  ],
+  collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'],
+  coverageDirectory: '<rootDir>/tests/unit/coverage',
+  // 'collectCoverage': true,
+  'coverageReporters': [
+    'lcov',
+    'text-summary'
+  ],
+  testURL: 'http://localhost/'
+}

+ 9 - 0
jsconfig.json

@@ -0,0 +1,9 @@
+{ 
+  "compilerOptions": {
+    "baseUrl": "./",
+    "paths": {
+        "@/*": ["src/*"]
+    }
+  },
+  "exclude": ["node_modules", "dist"]
+}

+ 129 - 0
package.json

@@ -0,0 +1,129 @@
+{
+  "name": "vue-element-admin",
+  "version": "4.2.1",
+  "license": "MIT",
+  "scripts": {
+    "dev": "vue-cli-service serve",
+    "build:prod": "vue-cli-service build",
+    "build:stage": "vue-cli-service build --mode staging",
+    "preview": "node build/index.js --preview",
+    "lint": "eslint --ext .js,.vue src",
+    "test:unit": "jest --clearCache && vue-cli-service test:unit",
+    "test:ci": "npm run lint && npm run test:unit",
+    "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
+    "new": "plop"
+  },
+  "husky": {
+    "hooks": {
+      "pre-commit": "lint-staged"
+    }
+  },
+  "lint-staged": {
+    "src/**/*.{js,vue}": [
+      "eslint --fix",
+      "git add"
+    ]
+  },
+  "keywords": [
+    "vue",
+    "admin",
+    "dashboard",
+    "element-ui",
+    "boilerplate",
+    "admin-template",
+    "management-system"
+  ],
+  "dependencies": {
+    "@antv/g6": "3.1.10",
+    "@antv/g6-editor": "^1.2.0",
+    "@antv/util": "1.3.1",
+    "@riophae/vue-treeselect": "0.4.0",
+    "ace-builds": "^1.4.12",
+    "axios": "^0.21.1",
+    "clipboard": "^2.0.6",
+    "codemirror": "^5.58.1",
+    "core-js": "^2.6.11",
+    "driver.js": "0.9.5",
+    "dropzone": "5.5.1",
+    "e-icon-picker": "1.0.7",
+    "echarts": "^4.8.0",
+    "element-ui": "^2.13.2",
+    "file-saver": "2.0.1",
+    "form-making": "^1.2.8",
+    "fuse.js": "3.4.4",
+    "js-cookie": "2.2.0",
+    "jsonlint": "1.6.3",
+    "jszip": "3.2.1",
+    "moment": "^2.27.0",
+    "monaco-editor": "^0.20.0",
+    "normalize.css": "7.0.0",
+    "nprogress": "0.2.0",
+    "numericjs": "^1.2.6",
+    "path-to-regexp": "2.4.0",
+    "qiniu-js": "^3.0.3",
+    "screenfull": "4.2.0",
+    "showdown": "^1.9.1",
+    "solarlunar": "^2.0.7",
+    "sortablejs": "1.8.4",
+    "tui-editor": "1.3.3",
+    "viewerjs": "^1.6.1",
+    "vue": "^2.6.12",
+    "vue-codemirror": "^4.0.6",
+    "vue-codemirror-lite": "^1.0.4",
+    "vue-count-to": "1.0.13",
+    "vue-cropper": "^0.5.0",
+    "vue-i18n": "^5.0.3",
+    "vue-loader": "^15.9.3",
+    "vue-particles": "^1.0.9",
+    "vue-quill-editor": "^3.0.6",
+    "vue-router": "3.0.2",
+    "vue-splitpane": "1.0.4",
+    "vue2-editor": "^2.10.2",
+    "vuedraggable": "2.20.0",
+    "vueify": "^9.4.1",
+    "vuex": "3.1.0",
+    "xlsx": "0.14.1"
+  },
+  "devDependencies": {
+    "@babel/core": "7.0.0",
+    "@babel/register": "^7.9.0",
+    "@vue/cli-plugin-babel": "3.5.3",
+    "@vue/cli-plugin-eslint": "^3.9.1",
+    "@vue/cli-plugin-unit-jest": "3.5.3",
+    "@vue/cli-service": "3.5.3",
+    "@vue/test-utils": "1.0.0-beta.29",
+    "autoprefixer": "^9.5.1",
+    "babel-core": "7.0.0-bridge.0",
+    "babel-eslint": "10.0.1",
+    "babel-jest": "23.6.0",
+    "beautifier": "^0.1.7",
+    "chalk": "2.4.2",
+    "chokidar": "2.1.5",
+    "connect": "3.6.6",
+    "eslint": "5.15.3",
+    "eslint-plugin-vue": "5.2.2",
+    "html-webpack-plugin": "3.2.0",
+    "husky": "1.3.1",
+    "lint-staged": "8.1.5",
+    "mockjs": "1.0.1-beta3",
+    "monaco-editor-webpack-plugin": "^1.9.0",
+    "node-sass": "^4.13.1",
+    "plop": "2.3.0",
+    "runjs": "^4.3.2",
+    "sass-loader": "^7.1.0",
+    "script-ext-html-webpack-plugin": "2.1.3",
+    "script-loader": "0.7.2",
+    "serve-static": "^1.13.2",
+    "svg-sprite-loader": "4.1.3",
+    "svgo": "1.2.0",
+    "vue-template-compiler": "^2.6.12"
+  },
+  "engines": {
+    "node": ">=8.9",
+    "npm": ">= 3.0.0"
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions"
+  ]
+}