Browse Source

初步开发完成

soft5566 3 years ago
parent
commit
4cca7f2872
100 changed files with 19628 additions and 17470 deletions
  1. 0 18
      .babelrc
  2. 5 0
      .editorconfig
  3. 5 0
      .env.development
  4. 6 0
      .env.production
  5. 8 0
      .env.staging
  6. 4 5
      .eslintignore
  7. 187 18
      .eslintrc.js
  8. 3 4
      .gitignore
  9. 5 0
      .travis.yml
  10. 21 0
      LICENSE
  11. 1 30
      README.md
  12. 14 0
      babel.config.js
  13. 0 41
      build/build.js
  14. 0 54
      build/check-versions.js
  15. 35 0
      build/index.js
  16. BIN
      build/logo.png
  17. 0 101
      build/utils.js
  18. 0 22
      build/vue-loader.conf.js
  19. 0 103
      build/webpack.base.conf.js
  20. 0 110
      build/webpack.dev.conf.js
  21. 0 149
      build/webpack.prod.conf.js
  22. 0 7
      config/dev.env.js
  23. 0 88
      config/index.js
  24. 0 4
      config/prod.env.js
  25. 0 7
      config/test.env.js
  26. 0 12
      index.html
  27. 24 0
      jest.config.js
  28. 9 0
      jsconfig.json
  29. 57 0
      mock/index.js
  30. 81 0
      mock/mock-server.js
  31. 29 0
      mock/table.js
  32. 86 0
      mock/user.js
  33. 25 0
      mock/utils.js
  34. 18445 15764
      package-lock.json
  35. 64 101
      package.json
  36. 2 4
      .postcssrc.js
  37. BIN
      public/favicon.ico
  38. 18 0
      public/index.html
  39. 95 27
      src/App.vue
  40. 65 0
      src/api/accountMgr.js
  41. 0 72
      src/api/acl/permission.js
  42. 0 83
      src/api/acl/role.js
  43. 0 132
      src/api/acl/user.js
  44. 0 59
      src/api/api.js
  45. 0 17
      src/api/doorLock.js
  46. 0 7
      src/api/fileServes.js
  47. 0 31
      src/api/fingerprint.js
  48. 0 32
      src/api/hotelAdmin.js
  49. 0 71
      src/api/hotelOrder.js
  50. 0 32
      src/api/hotelStaff.js
  51. 59 0
      src/api/house.js
  52. 0 32
      src/api/houseType.js
  53. 0 31
      src/api/icCard.js
  54. 0 12
      src/api/normalUser.js
  55. 60 0
      src/api/order.js
  56. 0 27
      src/api/room.js
  57. 0 25
      src/api/roomRealTimeStatu.js
  58. 0 17
      src/api/roomThirdSetting.js
  59. 0 13
      src/api/stat.js
  60. 16 0
      src/api/systemSet.js
  61. 0 13
      src/api/systemSetup.js
  62. 0 17
      src/api/systemnotice.js
  63. 30 0
      src/api/user.js
  64. BIN
      src/assets/404_images/404.png
  65. BIN
      src/assets/404_images/404_cloud.png
  66. 0 1
      src/assets/icons/svg/account-active.svg
  67. 0 1
      src/assets/icons/svg/account.svg
  68. 0 1
      src/assets/icons/svg/edit.svg
  69. 0 1
      src/assets/icons/svg/error.svg
  70. 0 1
      src/assets/icons/svg/home-active.svg
  71. 0 1
      src/assets/icons/svg/home.svg
  72. 0 1
      src/assets/icons/svg/item-logo.svg
  73. 0 1
      src/assets/icons/svg/order-active.svg
  74. 0 1
      src/assets/icons/svg/order.svg
  75. 0 1
      src/assets/icons/svg/quit.svg
  76. 0 1
      src/assets/icons/svg/sousuo.svg
  77. 0 1
      src/assets/icons/svg/staff-active.svg
  78. 0 1
      src/assets/icons/svg/staff.svg
  79. 0 1
      src/assets/icons/svg/stat-active.svg
  80. 0 1
      src/assets/icons/svg/stat.svg
  81. 0 1
      src/assets/icons/svg/system-active.svg
  82. 0 1
      src/assets/icons/svg/system.svg
  83. 0 1
      src/assets/icons/svg/tuifang.svg
  84. 0 1
      src/assets/icons/svg/xiaoxizhongxin.svg
  85. BIN
      src/assets/images/bg.png
  86. BIN
      src/assets/images/eye.png
  87. BIN
      src/assets/images/eye_close.png
  88. BIN
      src/assets/images/password.png
  89. BIN
      src/assets/images/user.png
  90. 0 0
      src/assets/scss/variable.scss
  91. 89 0
      src/components/Breadcrumb/index.vue
  92. 40 0
      src/components/Hamburger/index.vue
  93. 40 59
      src/components/SvgIcon/index.vue
  94. BIN
      src/icons/images/index/title_icon.png
  95. BIN
      src/icons/images/index/yewu.png
  96. BIN
      src/icons/images/index/yujing.png
  97. BIN
      src/icons/images/index/zhuangtai.png
  98. BIN
      src/icons/images/index/zoushi.png
  99. BIN
      src/icons/images/login/login_bg.png
  100. 0 0
      src/icons/images/login/login_form_bg.png

+ 0 - 18
.babelrc

@@ -1,18 +0,0 @@
-{
-  "presets": [
-    ["env", {
-      "modules": false,
-      "targets": {
-        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
-      }
-    }],
-    "stage-2"
-  ],
-  "plugins": ["transform-vue-jsx", "transform-runtime"],
-  "env": {
-    "test": {
-      "presets": ["env", "stage-2"],
-      "plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"]
-    }
-  }
-}

+ 5 - 0
.editorconfig

@@ -1,3 +1,4 @@
+# http://editorconfig.org
 root = true
 
 [*]
@@ -7,3 +8,7 @@ indent_size = 2
 end_of_line = lf
 insert_final_newline = true
 trim_trailing_whitespace = true
+
+[*.md]
+insert_final_newline = false
+trim_trailing_whitespace = false

+ 5 - 0
.env.development

@@ -0,0 +1,5 @@
+# just a flag
+ENV = 'development'
+
+# base api
+VUE_APP_BASE_API = ''

+ 6 - 0
.env.production

@@ -0,0 +1,6 @@
+# just a flag
+ENV = 'production'
+
+# base api
+VUE_APP_BASE_API = 'https://chtech.ncjti.edu.cn/air-conditioner-control/'
+

+ 8 - 0
.env.staging

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

+ 4 - 5
.eslintignore

@@ -1,5 +1,4 @@
-/build/
-/config/
-/dist/
-/*.js
-/test/unit/coverage/
+build/*.js
+src/assets
+public
+dist

+ 187 - 18
.eslintrc.js

@@ -1,29 +1,198 @@
-// https://eslint.org/docs/user-guide/configuring
-
 module.exports = {
   root: true,
   parserOptions: {
-    parser: 'babel-eslint'
+    parser: 'babel-eslint',
+    sourceType: 'module'
   },
   env: {
     browser: true,
+    node: true,
+    es6: true,
   },
-  extends: [
-    // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
-    // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
-    'plugin:vue/essential', 
-    // https://github.com/standard/standard/blob/master/docs/RULES-en.md
-    'standard'
-  ],
-  // required to lint *.vue files
-  plugins: [
-    'vue'
-  ],
+  extends: ['plugin:vue/recommended', 'eslint:recommended'],
+
   // add your custom rules here
+  //it is base on https://github.com/vuejs/eslint-config-vue
   rules: {
-    // allow async-await
-    'generator-star-spacing': 'off',
-    // allow debugger during development
-    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
+    "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']
   }
 }

+ 3 - 4
.gitignore

@@ -1,12 +1,11 @@
 .DS_Store
 node_modules/
-/dist/
+dist/
 npm-debug.log*
 yarn-debug.log*
 yarn-error.log*
-/test/unit/coverage/
-/test/e2e/reports/
-selenium-debug.log
+package-lock.json
+tests/**/coverage/
 
 # Editor directories and files
 .idea

+ 5 - 0
.travis.yml

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

+ 21 - 0
LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017-present PanJiaChen
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 1 - 30
README.md

@@ -1,30 +1 @@
-# admin
-
-> A Vue.js project
-
-## Build Setup
-
-``` bash
-# install dependencies
-npm install
-
-# serve with hot reload at localhost:8080
-npm run dev
-
-# build for production with minification
-npm run build
-
-# build for production and view the bundle analyzer report
-npm run build --report
-
-# run unit tests
-npm run unit
-
-# run e2e tests
-npm run e2e
-
-# run all tests
-npm test
-```
-
-For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
+#airConditionerWebManager

+ 14 - 0
babel.config.js

@@ -0,0 +1,14 @@
+module.exports = {
+  presets: [
+    // https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app
+    '@vue/cli-plugin-babel/preset'
+  ],
+  'env': {
+    'development': {
+      // babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require().
+      // This plugin can significantly increase the speed of hot updates, when you have a large number of pages.
+      // https://panjiachen.github.io/vue-element-admin-site/guide/advanced/lazy-loading.html
+      'plugins': ['dynamic-import-node']
+    }
+  }
+}

+ 0 - 41
build/build.js

@@ -1,41 +0,0 @@
-'use strict'
-require('./check-versions')()
-
-process.env.NODE_ENV = 'production'
-
-const ora = require('ora')
-const rm = require('rimraf')
-const path = require('path')
-const chalk = require('chalk')
-const webpack = require('webpack')
-const config = require('../config')
-const webpackConfig = require('./webpack.prod.conf')
-
-const spinner = ora('building for production...')
-spinner.start()
-
-rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
-  if (err) throw err
-  webpack(webpackConfig, (err, stats) => {
-    spinner.stop()
-    if (err) throw err
-    process.stdout.write(stats.toString({
-      colors: true,
-      modules: false,
-      children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
-      chunks: false,
-      chunkModules: false
-    }) + '\n\n')
-
-    if (stats.hasErrors()) {
-      console.log(chalk.red('  Build failed with errors.\n'))
-      process.exit(1)
-    }
-
-    console.log(chalk.cyan('  Build complete.\n'))
-    console.log(chalk.yellow(
-      '  Tip: built files are meant to be served over an HTTP server.\n' +
-      '  Opening index.html over file:// won\'t work.\n'
-    ))
-  })
-})

+ 0 - 54
build/check-versions.js

@@ -1,54 +0,0 @@
-'use strict'
-const chalk = require('chalk')
-const semver = require('semver')
-const packageConfig = require('../package.json')
-const shell = require('shelljs')
-
-function exec (cmd) {
-  return require('child_process').execSync(cmd).toString().trim()
-}
-
-const versionRequirements = [
-  {
-    name: 'node',
-    currentVersion: semver.clean(process.version),
-    versionRequirement: packageConfig.engines.node
-  }
-]
-
-if (shell.which('npm')) {
-  versionRequirements.push({
-    name: 'npm',
-    currentVersion: exec('npm --version'),
-    versionRequirement: packageConfig.engines.npm
-  })
-}
-
-module.exports = function () {
-  const warnings = []
-
-  for (let i = 0; i < versionRequirements.length; i++) {
-    const mod = versionRequirements[i]
-
-    if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
-      warnings.push(mod.name + ': ' +
-        chalk.red(mod.currentVersion) + ' should be ' +
-        chalk.green(mod.versionRequirement)
-      )
-    }
-  }
-
-  if (warnings.length) {
-    console.log('')
-    console.log(chalk.yellow('To use this template, you must update following to modules:'))
-    console.log()
-
-    for (let i = 0; i < warnings.length; i++) {
-      const warning = warnings[i]
-      console.log('  ' + warning)
-    }
-
-    console.log()
-    process.exit(1)
-  }
-}

+ 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}`)
+}

BIN
build/logo.png


+ 0 - 101
build/utils.js

@@ -1,101 +0,0 @@
-'use strict'
-const path = require('path')
-const config = require('../config')
-const ExtractTextPlugin = require('extract-text-webpack-plugin')
-const packageConfig = require('../package.json')
-
-exports.assetsPath = function (_path) {
-  const assetsSubDirectory = process.env.NODE_ENV === 'production'
-    ? config.build.assetsSubDirectory
-    : config.dev.assetsSubDirectory
-
-  return path.posix.join(assetsSubDirectory, _path)
-}
-
-exports.cssLoaders = function (options) {
-  options = options || {}
-
-  const cssLoader = {
-    loader: 'css-loader',
-    options: {
-      sourceMap: options.sourceMap
-    }
-  }
-
-  const postcssLoader = {
-    loader: 'postcss-loader',
-    options: {
-      sourceMap: options.sourceMap
-    }
-  }
-
-  // generate loader string to be used with extract text plugin
-  function generateLoaders (loader, loaderOptions) {
-    const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
-
-    if (loader) {
-      loaders.push({
-        loader: loader + '-loader',
-        options: Object.assign({}, loaderOptions, {
-          sourceMap: options.sourceMap
-        })
-      })
-    }
-
-    // Extract CSS when that option is specified
-    // (which is the case during production build)
-    if (options.extract) {
-      return ExtractTextPlugin.extract({
-        use: loaders,
-        fallback: 'vue-style-loader'
-      })
-    } else {
-      return ['vue-style-loader'].concat(loaders)
-    }
-  }
-
-  // https://vue-loader.vuejs.org/en/configurations/extract-css.html
-  return {
-    css: generateLoaders(),
-    postcss: generateLoaders(),
-    less: generateLoaders('less'),
-    sass: generateLoaders('sass', { indentedSyntax: true }),
-    scss: generateLoaders('sass'),
-    stylus: generateLoaders('stylus'),
-    styl: generateLoaders('stylus')
-  }
-}
-
-// Generate loaders for standalone style files (outside of .vue)
-exports.styleLoaders = function (options) {
-  const output = []
-  const loaders = exports.cssLoaders(options)
-
-  for (const extension in loaders) {
-    const loader = loaders[extension]
-    output.push({
-      test: new RegExp('\\.' + extension + '$'),
-      use: loader
-    })
-  }
-
-  return output
-}
-
-exports.createNotifierCallback = () => {
-  const notifier = require('node-notifier')
-
-  return (severity, errors) => {
-    if (severity !== 'error') return
-
-    const error = errors[0]
-    const filename = error.file && error.file.split('!').pop()
-
-    notifier.notify({
-      title: packageConfig.name,
-      message: severity + ': ' + error.name,
-      subtitle: filename || '',
-      icon: path.join(__dirname, 'logo.png')
-    })
-  }
-}

+ 0 - 22
build/vue-loader.conf.js

@@ -1,22 +0,0 @@
-'use strict'
-const utils = require('./utils')
-const config = require('../config')
-const isProduction = process.env.NODE_ENV === 'production'
-const sourceMapEnabled = isProduction
-  ? config.build.productionSourceMap
-  : config.dev.cssSourceMap
-
-module.exports = {
-  loaders: utils.cssLoaders({
-    sourceMap: sourceMapEnabled,
-    extract: isProduction
-  }),
-  cssSourceMap: sourceMapEnabled,
-  cacheBusting: config.dev.cacheBusting,
-  transformToRequire: {
-    video: ['src', 'poster'],
-    source: 'src',
-    img: 'src',
-    image: 'xlink:href'
-  }
-}

+ 0 - 103
build/webpack.base.conf.js

@@ -1,103 +0,0 @@
-'use strict'
-const path = require('path')
-const utils = require('./utils')
-const config = require('../config')
-const vueLoaderConfig = require('./vue-loader.conf')
-
-function resolve (dir) {
-  return path.join(__dirname, '..', dir)
-}
-
-const createLintingRule = () => ({
-  test: /\.(js|vue)$/,
-  loader: 'eslint-loader',
-  enforce: 'pre',
-  include: [resolve('src'), resolve('test')],
-  options: {
-    formatter: require('eslint-friendly-formatter'),
-    emitWarning: !config.dev.showEslintErrorsInOverlay
-  }
-})
-
-module.exports = {
-  context: path.resolve(__dirname, '../'),
-  entry: {
-    app: './src/main.js'
-  },
-  output: {
-    path: config.build.assetsRoot,
-    filename: '[name].js',
-    publicPath: process.env.NODE_ENV === 'production'
-      ? config.build.assetsPublicPath
-      : config.dev.assetsPublicPath
-  },
-  resolve: {
-    extensions: ['.js', '.vue', '.json'],
-    alias: {
-      'vue$': 'vue/dist/vue.esm.js',
-      '@': resolve('src'),
-    }
-  },
-  module: {
-    rules: [
-      ...(config.dev.useEslint ? [] : []),// 开启eslint 将后面改成 [createLintingRule()] : []
-      {
-        test: /(\.svg)(\?.*)?$/,
-        loader: 'svg-sprite-loader',
-        include: [resolve('src/assets/icons/svg')],
-        options: {
-          symbolId: 'icon-[name]'
-        }
-      },
-      
-      {
-        test: /\.vue$/,
-        loader: 'vue-loader',
-        options: vueLoaderConfig
-      },
-      {
-        test: /\.js$/,
-        loader: 'babel-loader',
-        include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
-      },
-      {
-        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
-        loader: 'url-loader',
-        exclude: [resolve('src/assets/icons/svg')],
-        options: {
-          limit: 10000,
-          name: utils.assetsPath('img/[name].[hash:7].[ext]')
-        }
-      },
-      
-      {
-        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
-        loader: 'url-loader',
-        options: {
-          limit: 10000,
-          name: utils.assetsPath('media/[name].[hash:7].[ext]')
-        }
-      },
-      {
-        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
-        loader: 'url-loader',
-        options: {
-          limit: 10000,
-          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
-        }
-      }
-    ]
-  },
-  node: {
-    // prevent webpack from injecting useless setImmediate polyfill because Vue
-    // source contains it (although only uses it if it's native).
-    setImmediate: false,
-    // prevent webpack from injecting mocks to Node native modules
-    // that does not make sense for the client
-    dgram: 'empty',
-    fs: 'empty',
-    net: 'empty',
-    tls: 'empty',
-    child_process: 'empty'
-  }
-}

+ 0 - 110
build/webpack.dev.conf.js

@@ -1,110 +0,0 @@
-"use strict";
-const utils = require("./utils");
-const webpack = require("webpack");
-const config = require("../config");
-const merge = require("webpack-merge");
-const path = require("path");
-const baseWebpackConfig = require("./webpack.base.conf");
-const CopyWebpackPlugin = require("copy-webpack-plugin");
-const HtmlWebpackPlugin = require("html-webpack-plugin");
-const FriendlyErrorsPlugin = require("friendly-errors-webpack-plugin");
-const portfinder = require("portfinder");
-
-const HOST = process.env.HOST;
-const PORT = process.env.PORT && Number(process.env.PORT);
-
-const devWebpackConfig = merge(baseWebpackConfig, {
-  module: {
-    rules: utils.styleLoaders({
-      sourceMap: config.dev.cssSourceMap,
-      usePostCSS: true
-    })
-  },
-  // cheap-module-eval-source-map is faster for development
-  devtool: config.dev.devtool,
-
-  // these devServer options should be customized in /config/index.js
-  devServer: {
-    clientLogLevel: "warning",
-    historyApiFallback: {
-      rewrites: [
-        {
-          from: /.*/,
-          to: path.posix.join(config.dev.assetsPublicPath, "index.html")
-        }
-      ]
-    },
-    // useLocalIp: true, //将useLoackIp设置为true 就可以了
-    hot: true,
-    contentBase: false, // since we use CopyWebpackPlugin.
-    compress: true,
-    host: HOST || config.dev.host,
-    port: PORT || config.dev.port,
-    open: config.dev.autoOpenBrowser,
-    overlay: config.dev.errorOverlay
-      ? { warnings: false, errors: true }
-      : false,
-    publicPath: config.dev.assetsPublicPath,
-    proxy: config.dev.proxyTable,
-    quiet: true, // necessary for FriendlyErrorsPlugin
-    watchOptions: {
-      poll: config.dev.poll
-    }
-  },
-  plugins: [
-    new webpack.DefinePlugin({
-      "process.env": require("../config/dev.env")
-    }),
-    new webpack.HotModuleReplacementPlugin(),
-    new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
-    new webpack.NoEmitOnErrorsPlugin(),
-    // https://github.com/ampedandwired/html-webpack-plugin
-    new HtmlWebpackPlugin({
-      filename: "index.html",
-      template: "index.html",
-      inject: true
-    }),
-    // copy custom static assets
-    new CopyWebpackPlugin([
-      {
-        from: path.resolve(__dirname, "../static"),
-        to: config.dev.assetsSubDirectory,
-        ignore: [".*"]
-      }
-    ])
-  ]
-});
-
-module.exports = new Promise((resolve, reject) => {
-  portfinder.basePort = process.env.PORT || config.dev.port;
-  portfinder.getPort((err, port) => {
-    if (err) {
-      reject(err);
-    } else {
-      // publish the new Port, necessary for e2e tests
-      process.env.PORT = port;
-      // add port to devServer config
-      devWebpackConfig.devServer.port = port;
-
-      // Add FriendlyErrorsPlugin
-      devWebpackConfig.plugins.push(
-        new FriendlyErrorsPlugin({
-          compilationSuccessInfo: {
-            messages: [
-              //下面两个地方,直接复制即可
-              `App runing at: `,
-              ` - Local: http://localhost:${port}`, //配置这里
-              ` - Network: http://${require("ip").address()}:${port}` //配置这里
-            ]
-            // messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
-          },
-          onErrors: config.dev.notifyOnErrors
-            ? utils.createNotifierCallback()
-            : undefined
-        })
-      );
-
-      resolve(devWebpackConfig);
-    }
-  });
-});

+ 0 - 149
build/webpack.prod.conf.js

@@ -1,149 +0,0 @@
-'use strict'
-const path = require('path')
-const utils = require('./utils')
-const webpack = require('webpack')
-const config = require('../config')
-const merge = require('webpack-merge')
-const baseWebpackConfig = require('./webpack.base.conf')
-const CopyWebpackPlugin = require('copy-webpack-plugin')
-const HtmlWebpackPlugin = require('html-webpack-plugin')
-const ExtractTextPlugin = require('extract-text-webpack-plugin')
-const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
-const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
-
-const env = process.env.NODE_ENV === 'testing'
-  ? require('../config/test.env')
-  : require('../config/prod.env')
-
-const webpackConfig = merge(baseWebpackConfig, {
-  module: {
-    rules: utils.styleLoaders({
-      sourceMap: config.build.productionSourceMap,
-      extract: true,
-      usePostCSS: true
-    })
-  },
-  devtool: config.build.productionSourceMap ? config.build.devtool : false,
-  output: {
-    path: config.build.assetsRoot,
-    filename: utils.assetsPath('js/[name].[chunkhash].js'),
-    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
-  },
-  plugins: [
-    // http://vuejs.github.io/vue-loader/en/workflow/production.html
-    new webpack.DefinePlugin({
-      'process.env': env
-    }),
-    new UglifyJsPlugin({
-      uglifyOptions: {
-        compress: {
-          warnings: false
-        }
-      },
-      sourceMap: config.build.productionSourceMap,
-      parallel: true
-    }),
-    // extract css into its own file
-    new ExtractTextPlugin({
-      filename: utils.assetsPath('css/[name].[contenthash].css'),
-      // Setting the following option to `false` will not extract CSS from codesplit chunks.
-      // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
-      // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`, 
-      // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
-      allChunks: true,
-    }),
-    // Compress extracted CSS. We are using this plugin so that possible
-    // duplicated CSS from different components can be deduped.
-    new OptimizeCSSPlugin({
-      cssProcessorOptions: config.build.productionSourceMap
-        ? { safe: true, map: { inline: false } }
-        : { safe: true }
-    }),
-    // generate dist index.html with correct asset hash for caching.
-    // you can customize output by editing /index.html
-    // see https://github.com/ampedandwired/html-webpack-plugin
-    new HtmlWebpackPlugin({
-      filename: process.env.NODE_ENV === 'testing'
-        ? 'index.html'
-        : config.build.index,
-      template: 'index.html',
-      inject: true,
-      minify: {
-        removeComments: true,
-        collapseWhitespace: true,
-        removeAttributeQuotes: true
-        // more options:
-        // https://github.com/kangax/html-minifier#options-quick-reference
-      },
-      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
-      chunksSortMode: 'dependency'
-    }),
-    // keep module.id stable when vendor modules does not change
-    new webpack.HashedModuleIdsPlugin(),
-    // enable scope hoisting
-    new webpack.optimize.ModuleConcatenationPlugin(),
-    // split vendor js into its own file
-    new webpack.optimize.CommonsChunkPlugin({
-      name: 'vendor',
-      minChunks (module) {
-        // any required modules inside node_modules are extracted to vendor
-        return (
-          module.resource &&
-          /\.js$/.test(module.resource) &&
-          module.resource.indexOf(
-            path.join(__dirname, '../node_modules')
-          ) === 0
-        )
-      }
-    }),
-    // extract webpack runtime and module manifest to its own file in order to
-    // prevent vendor hash from being updated whenever app bundle is updated
-    new webpack.optimize.CommonsChunkPlugin({
-      name: 'manifest',
-      minChunks: Infinity
-    }),
-    // This instance extracts shared chunks from code splitted chunks and bundles them
-    // in a separate chunk, similar to the vendor chunk
-    // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
-    new webpack.optimize.CommonsChunkPlugin({
-      name: 'app',
-      async: 'vendor-async',
-      children: true,
-      minChunks: 3
-    }),
-
-    // copy custom static assets
-    new CopyWebpackPlugin([
-      {
-        from: path.resolve(__dirname, '../static'),
-        to: config.build.assetsSubDirectory,
-        ignore: ['.*']
-      }
-    ])
-  ]
-})
-
-if (config.build.productionGzip) {
-  const CompressionWebpackPlugin = require('compression-webpack-plugin')
-
-  webpackConfig.plugins.push(
-    new CompressionWebpackPlugin({
-      asset: '[path].gz[query]',
-      algorithm: 'gzip',
-      test: new RegExp(
-        '\\.(' +
-        config.build.productionGzipExtensions.join('|') +
-        ')$'
-      ),
-      threshold: 10240,
-      minRatio: 0.8
-    })
-  )
-}
-
-if (config.build.bundleAnalyzerReport) {
-  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
-  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
-}
-
-module.exports = webpackConfig

+ 0 - 7
config/dev.env.js

@@ -1,7 +0,0 @@
-'use strict'
-const merge = require('webpack-merge')
-const prodEnv = require('./prod.env')
-
-module.exports = merge(prodEnv, {
-  NODE_ENV: '"development"'
-})

+ 0 - 88
config/index.js

@@ -1,88 +0,0 @@
-"use strict";
-// Template version: 1.3.1
-// see http://vuejs-templates.github.io/webpack for documentation.
-
-const path = require("path");
-
-module.exports = {
-  dev: {
-    // http://192.168.161.34:8089线下地址
-    // https://chtech.ncjti.edu.cn/hotel/ihotel-api线上地址
-    // Paths
-    assetsSubDirectory: "static",
-    assetsPublicPath: "/hotel/manage/",
-    proxyTable: {
-      "/hotel/ihotel-api": {
-        // target: 'http://192.168.161.34:8089',
-        target: "https://chtech.ncjti.edu.cn/hotel/ihotel-api",
-        secure: false, // 这是签名认证,http和https区分的参数设置
-        changeOrigin: true,
-        pathRewrite: {
-          "^/hotel/ihotel-api": ""
-        }
-      }
-    },
-
-    // Various Dev Server settings
-    host: "0.0.0.0", // can be overwritten by process.env.HOST
-    // host: "localhost",
-    port: 8899, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
-    autoOpenBrowser: false,
-    errorOverlay: true,
-    notifyOnErrors: true,
-    poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
-
-    // Use Eslint Loader?
-    // If true, your code will be linted during bundling and
-    // linting errors and warnings will be shown in the console.
-    useEslint: true,
-    // If true, eslint errors and warnings will also be shown in the error overlay
-    // in the browser.
-    showEslintErrorsInOverlay: false,
-
-    /**
-     * Source Maps
-     */
-
-    // https://webpack.js.org/configuration/devtool/#development
-    devtool: "cheap-module-eval-source-map",
-
-    // If you have problems debugging vue-files in devtools,
-    // set this to false - it *may* help
-    // https://vue-loader.vuejs.org/en/options.html#cachebusting
-    cacheBusting: true,
-
-    cssSourceMap: true
-  },
-
-  build: {
-    // Template for index.html
-    index: path.resolve(__dirname, "../dist/index.html"),
-
-    // Paths
-    assetsRoot: path.resolve(__dirname, "../dist"),
-    assetsSubDirectory: "static",
-    assetsPublicPath: "/hotel/manage/",
-
-    /**
-     * Source Maps
-     */
-
-    productionSourceMap: true,
-    // https://webpack.js.org/configuration/devtool/#production
-    devtool: "#source-map",
-
-    // Gzip off by default as many popular static hosts such as
-    // Surge or Netlify already gzip all static assets for you.
-    // Before setting to `true`, make sure to:
-    // npm install --save-dev compression-webpack-plugin
-    productionGzip: false,
-    productionGzipExtensions: ["js", "css"],
-
-    // Run the build command with an extra argument to
-    // View the bundle analyzer report after build finishes:
-    // `npm run build --report`
-    // Set to `true` or `false` to always turn it on or off
-    bundleAnalyzerReport: process.env.npm_config_report
-  }
-};

+ 0 - 4
config/prod.env.js

@@ -1,4 +0,0 @@
-'use strict'
-module.exports = {
-  NODE_ENV: '"production"'
-}

+ 0 - 7
config/test.env.js

@@ -1,7 +0,0 @@
-'use strict'
-const merge = require('webpack-merge')
-const devEnv = require('./dev.env')
-
-module.exports = merge(devEnv, {
-  NODE_ENV: '"testing"'
-})

+ 0 - 12
index.html

@@ -1,12 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="utf-8" />
-    <meta name="viewport" content="width=device-width,initial-scale=1.0" />
-    <title>智慧校园公寓管理</title>
-  </head>
-  <body>
-    <div id="app"></div>
-    <!-- built files will be auto injected -->
-  </body>
-</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"]
+}

+ 57 - 0
mock/index.js

@@ -0,0 +1,57 @@
+const Mock = require('mockjs')
+const { param2Obj } = require('./utils')
+
+const user = require('./user')
+const table = require('./table')
+
+const mocks = [
+  ...user,
+  ...table
+]
+
+// for front mock
+// please use it cautiously, it will redefine XMLHttpRequest,
+// which will cause many of your third-party libraries to be invalidated(like progress event).
+function mockXHR() {
+  // mock patch
+  // https://github.com/nuysoft/Mock/issues/300
+  Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
+  Mock.XHR.prototype.send = function() {
+    if (this.custom.xhr) {
+      this.custom.xhr.withCredentials = this.withCredentials || false
+
+      if (this.responseType) {
+        this.custom.xhr.responseType = this.responseType
+      }
+    }
+    this.proxy_send(...arguments)
+  }
+
+  function XHR2ExpressReqWrap(respond) {
+    return function(options) {
+      let result = null
+      if (respond instanceof Function) {
+        const { body, type, url } = options
+        // https://expressjs.com/en/4x/api.html#req
+        result = respond({
+          method: type,
+          body: JSON.parse(body),
+          query: param2Obj(url)
+        })
+      } else {
+        result = respond
+      }
+      return Mock.mock(result)
+    }
+  }
+
+  for (const i of mocks) {
+    Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response))
+  }
+}
+
+module.exports = {
+  mocks,
+  mockXHR
+}
+

+ 81 - 0
mock/mock-server.js

@@ -0,0 +1,81 @@
+const chokidar = require('chokidar')
+const bodyParser = require('body-parser')
+const chalk = require('chalk')
+const path = require('path')
+const Mock = require('mockjs')
+
+const mockDir = path.join(process.cwd(), 'mock')
+
+function registerRoutes(app) {
+  let mockLastIndex
+  const { mocks } = require('./index.js')
+  const mocksForServer = mocks.map(route => {
+    return responseFake(route.url, route.type, route.response)
+  })
+  for (const mock of mocksForServer) {
+    app[mock.type](mock.url, mock.response)
+    mockLastIndex = app._router.stack.length
+  }
+  const mockRoutesLength = Object.keys(mocksForServer).length
+  return {
+    mockRoutesLength: mockRoutesLength,
+    mockStartIndex: mockLastIndex - mockRoutesLength
+  }
+}
+
+function unregisterRoutes() {
+  Object.keys(require.cache).forEach(i => {
+    if (i.includes(mockDir)) {
+      delete require.cache[require.resolve(i)]
+    }
+  })
+}
+
+// for mock server
+const responseFake = (url, type, respond) => {
+  return {
+    url: new RegExp(`${process.env.VUE_APP_BASE_API}${url}`),
+    type: type || 'get',
+    response(req, res) {
+      console.log('request invoke:' + req.path)
+      res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))
+    }
+  }
+}
+
+module.exports = app => {
+  // parse app.body
+  // https://expressjs.com/en/4x/api.html#req.body
+  app.use(bodyParser.json())
+  app.use(bodyParser.urlencoded({
+    extended: true
+  }))
+
+  const mockRoutes = registerRoutes(app)
+  var mockRoutesLength = mockRoutes.mockRoutesLength
+  var mockStartIndex = mockRoutes.mockStartIndex
+
+  // watch files, hot reload mock server
+  chokidar.watch(mockDir, {
+    ignored: /mock-server/,
+    ignoreInitial: true
+  }).on('all', (event, path) => {
+    if (event === 'change' || event === 'add') {
+      try {
+        // remove mock routes stack
+        app._router.stack.splice(mockStartIndex, mockRoutesLength)
+
+        // clear routes cache
+        unregisterRoutes()
+
+        const mockRoutes = registerRoutes(app)
+        mockRoutesLength = mockRoutes.mockRoutesLength
+        mockStartIndex = mockRoutes.mockStartIndex
+
+        console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed  ${path}`))
+      } catch (error) {
+        console.log(chalk.redBright(error))
+      }
+    }
+  })
+}

+ 29 - 0
mock/table.js

@@ -0,0 +1,29 @@
+const Mock = require('mockjs')
+
+const data = Mock.mock({
+  'items|30': [{
+    id: '@id',
+    title: '@sentence(10, 20)',
+    'status|1': ['published', 'draft', 'deleted'],
+    author: 'name',
+    display_time: '@datetime',
+    pageviews: '@integer(300, 5000)'
+  }]
+})
+
+module.exports = [
+  {
+    url: '/vue-admin-template/table/list',
+    type: 'get',
+    response: config => {
+      const items = data.items
+      return {
+        code: 20000,
+        data: {
+          total: items.length,
+          items: items
+        }
+      }
+    }
+  }
+]

+ 86 - 0
mock/user.js

@@ -0,0 +1,86 @@
+
+const tokens = {
+  admin: {
+    token: 'admin-token'
+  },
+  editor: {
+    token: 'editor-token'
+  }
+}
+
+const users = {
+  'admin-token': {
+    roles: ['admin'],
+    introduction: 'I am a super administrator',
+    // avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
+    avatar: '',
+    name: 'Super Admin'
+  },
+  'editor-token': {
+    roles: ['editor'],
+    introduction: 'I am an editor',
+    // avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
+    avatar: 'f',
+    name: 'Normal Editor'
+  }
+}
+
+module.exports = [
+  // user login
+  {
+    url: '/vue-admin-template/user/login',
+    type: 'post',
+    response: config => {
+      const { username } = config.body
+      const token = tokens[username]
+
+      // mock error
+      if (!token) {
+        return {
+          code: 60204,
+          message: 'Account and password are incorrect.'
+        }
+      }
+
+      return {
+        code: 20000,
+        data: token
+      }
+    }
+  },
+
+  // get user info
+  {
+    url: '/vue-admin-template/user/info\.*',
+    type: 'get',
+    response: config => {
+      const { token } = config.query
+      const info = users[token]
+
+      // mock error
+      if (!info) {
+        return {
+          code: 50008,
+          message: 'Login failed, unable to get user details.'
+        }
+      }
+
+      return {
+        code: 20000,
+        data: info
+      }
+    }
+  },
+
+  // user logout
+  {
+    url: '/vue-admin-template/user/logout',
+    type: 'post',
+    response: _ => {
+      return {
+        code: 20000,
+        data: 'success'
+      }
+    }
+  }
+]

+ 25 - 0
mock/utils.js

@@ -0,0 +1,25 @@
+/**
+ * @param {string} url
+ * @returns {Object}
+ */
+function param2Obj(url) {
+  const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
+  if (!search) {
+    return {}
+  }
+  const obj = {}
+  const searchArr = search.split('&')
+  searchArr.forEach(v => {
+    const index = v.indexOf('=')
+    if (index !== -1) {
+      const name = v.substring(0, index)
+      const val = v.substring(index + 1, v.length)
+      obj[name] = val
+    }
+  })
+  return obj
+}
+
+module.exports = {
+  param2Obj
+}

File diff suppressed because it is too large
+ 18445 - 15764
package-lock.json


+ 64 - 101
package.json

@@ -1,102 +1,65 @@
 {
-  "name": "admin",
-  "version": "1.0.0",
-  "description": "A Vue.js project",
-  "author": "hzj2232462644 <hzj2232462644@163.com>",
-  "private": true,
-  "scripts": {
-    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js --host 0.0.0.0",
-    "start": "npm run dev",
-    "unit": "jest --config test/unit/jest.conf.js --coverage",
-    "e2e": "node test/e2e/runner.js",
-    "test": "npm run unit && npm run e2e",
-    "lint": "eslint --ext .js,.vue src test/unit test/e2e/specs",
-    "build": "node build/build.js"
-  },
-  "dependencies": {
-    "axios": "^0.27.2",
-    "better-scroll": "^2.4.2",
-    "dayjs": "^1.11.5",
-    "element-ui": "^2.15.2",
-    "file-saver": "^2.0.5",
-    "js-cookie": "^3.0.1",
-    "jsencrypt": "^3.2.1",
-    "lodash": "^4.17.21",
-    "moment": "^2.29.4",
-    "svg-sprite-loader": "^4.3.0",
-    "vue": "^2.5.2",
-    "vue-router": "^3.0.1",
-    "vuex": "^3.6.2",
-    "vuex-persistedstate": "^4.1.0",
-    "xlsx": "^0.18.5"
-  },
-  "devDependencies": {
-    "autoprefixer": "^7.1.2",
-    "babel-core": "^6.22.1",
-    "babel-eslint": "^8.2.1",
-    "babel-helper-vue-jsx-merge-props": "^2.0.3",
-    "babel-jest": "^21.0.2",
-    "babel-loader": "^7.1.1",
-    "babel-plugin-dynamic-import-node": "^1.2.0",
-    "babel-plugin-syntax-jsx": "^6.18.0",
-    "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
-    "babel-plugin-transform-runtime": "^6.22.0",
-    "babel-plugin-transform-vue-jsx": "^3.5.0",
-    "babel-preset-env": "^1.3.2",
-    "babel-preset-stage-2": "^6.22.0",
-    "babel-register": "^6.22.0",
-    "chalk": "^2.0.1",
-    "chromedriver": "^2.27.2",
-    "copy-webpack-plugin": "^4.0.1",
-    "cross-spawn": "^5.0.1",
-    "css-loader": "^0.28.0",
-    "eslint": "^4.15.0",
-    "eslint-config-standard": "^10.2.1",
-    "eslint-friendly-formatter": "^3.0.0",
-    "eslint-loader": "^1.7.1",
-    "eslint-plugin-import": "^2.7.0",
-    "eslint-plugin-node": "^5.2.0",
-    "eslint-plugin-promise": "^3.4.0",
-    "eslint-plugin-standard": "^3.0.1",
-    "eslint-plugin-vue": "^4.0.0",
-    "extract-text-webpack-plugin": "^3.0.0",
-    "file-loader": "^1.1.4",
-    "friendly-errors-webpack-plugin": "^1.6.1",
-    "html-webpack-plugin": "^2.30.1",
-    "jest": "^22.0.4",
-    "jest-serializer-vue": "^0.3.0",
-    "nightwatch": "^0.9.12",
-    "node-notifier": "^5.1.2",
-    "node-sass": "^4.14.1",
-    "optimize-css-assets-webpack-plugin": "^3.2.0",
-    "ora": "^1.2.0",
-    "portfinder": "^1.0.13",
-    "postcss-import": "^11.0.0",
-    "postcss-loader": "^2.0.8",
-    "postcss-url": "^7.2.1",
-    "rimraf": "^2.6.0",
-    "sass-loader": "^7.3.1",
-    "selenium-server": "^3.0.1",
-    "semver": "^5.3.0",
-    "shelljs": "^0.7.6",
-    "uglifyjs-webpack-plugin": "^1.1.1",
-    "url-loader": "^0.5.8",
-    "vue-jest": "^1.0.2",
-    "vue-loader": "^13.3.0",
-    "vue-style-loader": "^3.0.1",
-    "vue-template-compiler": "^2.5.2",
-    "webpack": "^3.6.0",
-    "webpack-bundle-analyzer": "^2.9.0",
-    "webpack-dev-server": "^2.9.1",
-    "webpack-merge": "^4.1.0"
-  },
-  "engines": {
-    "node": ">= 6.0.0",
-    "npm": ">= 3.0.0"
-  },
-  "browserslist": [
-    "> 1%",
-    "last 2 versions",
-    "not ie <= 8"
-  ]
-}
+	"name": "vue-admin-template",
+	"version": "4.4.0",
+	"description": "A vue admin template with Element UI & axios & iconfont & permission control & lint",
+	"author": "Pan <panfree23@gmail.com>",
+	"scripts": {
+		"build": "set NODE_OPTIONS=--openssl-legacy-provider & vue-cli-service build",
+		"build:report": "set NODE_OPTIONS=--openssl-legacy-provider & vue-cli-service build --report",
+		"build:prod": "vue-cli-service build",
+		"build:stage": "vue-cli-service build --mode staging",
+		"dev": "set NODE_OPTIONS=--openssl-legacy-provider & vue-cli-service serve",
+		"preview": "node build/index.js --preview",
+		"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
+		"lint": "eslint --ext .js,.vue src",
+		"test:unit": "jest --clearCache && vue-cli-service test:unit",
+		"test:ci": "npm run lint && npm run test:unit"
+	},
+	"dependencies": {
+		"axios": "0.18.1",
+		"core-js": "3.6.5",
+		"echarts": "^5.3.3",
+		"element-ui": "2.13.2",
+		"js-cookie": "2.2.0",
+		"normalize.css": "7.0.0",
+		"nprogress": "0.2.0",
+		"path-to-regexp": "2.4.0",
+		"vue": "2.6.10",
+		"vue-router": "3.0.6",
+		"vuex": "3.1.0"
+	},
+	"devDependencies": {
+		"@vue/cli-plugin-babel": "4.4.4",
+		"@vue/cli-plugin-eslint": "4.4.4",
+		"@vue/cli-plugin-unit-jest": "4.4.4",
+		"@vue/cli-service": "4.4.4",
+		"@vue/test-utils": "1.0.0-beta.29",
+		"autoprefixer": "9.5.1",
+		"babel-eslint": "10.1.0",
+		"babel-jest": "23.6.0",
+		"babel-plugin-dynamic-import-node": "2.3.3",
+		"chalk": "2.4.2",
+		"connect": "3.6.6",
+		"eslint": "6.7.2",
+		"eslint-plugin-vue": "6.2.2",
+		"html-webpack-plugin": "3.2.0",
+		"mockjs": "1.0.1-beta3",
+		"runjs": "4.3.2",
+		"sass": "1.26.8",
+		"sass-loader": "8.0.2",
+		"script-ext-html-webpack-plugin": "2.1.3",
+		"serve-static": "1.13.2",
+		"svg-sprite-loader": "4.1.3",
+		"svgo": "1.2.2",
+		"vue-template-compiler": "2.6.10"
+	},
+	"browserslist": [
+		"> 1%",
+		"last 2 versions"
+	],
+	"engines": {
+		"node": ">=8.9",
+		"npm": ">= 3.0.0"
+	},
+	"license": "MIT"
+}

+ 2 - 4
.postcssrc.js

@@ -1,10 +1,8 @@
 // https://github.com/michael-ciniawsky/postcss-load-config
 
 module.exports = {
-  "plugins": {
-    "postcss-import": {},
-    "postcss-url": {},
+  'plugins': {
     // to edit target browsers: use "browserslist" field in package.json
-    "autoprefixer": {}
+    'autoprefixer': {}
   }
 }

BIN
public/favicon.ico


+ 18 - 0
public/index.html

@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+	<head>
+		<meta charset="utf-8">
+		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
+		<link rel="icon" href="<%= BASE_URL %>favicon.ico">
+		<title><%= webpackConfig.name %></title>
+	</head>
+	<body>
+		<noscript>
+			<strong>We're sorry but <%= webpackConfig.name %> doesn't work properly without JavaScript enabled. Please
+				enable it to continue.</strong>
+		</noscript>
+		<div id="app"></div>
+		<!-- built files will be auto injected -->
+	</body>
+</html>

+ 95 - 27
src/App.vue

@@ -1,33 +1,101 @@
 <template>
-  <div id="app">
-    <router-view></router-view>
-  </div>
+	<div id="app">
+		<router-view />
+	</div>
 </template>
 
 <script>
-export default {
-  name: "App",
-  mounted() {},
-};
-</script>
+	let timmer = null //超时退出 定时器 必须放到全局,解决vue数据同步导致无法清除定时器
+	export default {
+		name: 'App',
+		data() {
+			return {
+				lastTime: null, //超时退出 最后时间
+			}
+		},
+		created() {
+			// 在页面加载时读取sessionStorage里的状态信息
+			if (sessionStorage.getItem('store')) {
+				this.$store.replaceState(
+					Object.assign({},
+						this.$store.state,
+						JSON.parse(sessionStorage.getItem('store'))
+					)
+				)
+			}
+			// 在页面刷新时将vuex里的信息保存到sessionStorage里
+			// beforeunload事件在页面刷新时先触发
+			window.addEventListener('beforeunload', () => {
+				sessionStorage.setItem('store', JSON.stringify(this.$store.state))
+			});
+			// 超时退出 start
+			this.lastTime = new Date();
+
+			window.addEventListener('resize', () => {
+				if (timmer) {
+					clearTimeout(timmer);
+				}
+				timmer = setTimeout(() => {
+					if (this.$route.path != '/login') {
+						this.currentTime();
+					}
+				}, 1000)
+			})
 
-<style lang="scss">
-#app {
-  font-family: "Avenir", Helvetica, Arial, sans-serif;
-  -webkit-font-smoothing: antialiased;
-  -moz-osx-font-smoothing: grayscale;
-  width: 100%;
-  height: 100%;
-}
+			window.addEventListener('click', () => {
+				if (timmer) {
+					clearTimeout(timmer);
+				}
+				timmer = setTimeout(() => {
+					if (this.$route.path != '/login') {
+						this.currentTime();
+					}
+				}, 1000)
+			})
 
-html,
-body {
-  margin: 0;
-  padding: 0;
-  width: 100%;
-  height: 100%;
-  ::-webkit-scrollbar {
-    display: none; /* Chrome Safari */
-  }
-}
-</style>
+			window.addEventListener('scroll', () => {
+				if (timmer) {
+					clearTimeout(timmer);
+				}
+				timmer = setTimeout(() => {
+					if (this.$route.path != '/login') {
+						this.currentTime();
+					}
+				}, 1000)
+			}, true)
+
+			window.addEventListener('mousemove', () => {
+				if (timmer) {
+					clearTimeout(timmer);
+				}
+				timmer = setTimeout(() => {
+					if (this.$route.path != '/login') {
+						this.currentTime();
+					}
+				}, 1000)
+			}, true)
+			// 超时退出 end
+		},
+		methods: {
+			currentTime() { // 超时退出     
+				const currentTime = new Date();
+				if (currentTime - this.lastTime > 1000 * 60 * 60 * 6) {
+					this.lastTime = currentTime
+					if (this.$route.path != '/login') {
+						this.$message({
+							message: '登录超时,将返回登录页',
+							type: 'error',
+							duration: 2000
+						})
+						setTimeout(() => {
+							this.$store.dispatch('user/logout')
+							this.$router.push(`/login?redirect=${this.$route.fullPath}`)
+						}, 2000)
+					}
+				} else {
+					this.lastTime = currentTime;
+				}
+			}
+		}
+	}
+</script>

+ 65 - 0
src/api/accountMgr.js

@@ -0,0 +1,65 @@
+import request from '@/utils/request';
+
+// 获取账号列表数据
+export function getTableData(forData) {
+	let data = new FormData();
+	data.append('page', forData.page);
+	data.append('rows', forData.rows);
+  
+	return request({
+		url: '/adminlist.action',
+		method: 'post',
+		data
+	});
+};
+
+// 新增管理员
+export function addAccount(param) {
+	let data = {
+		admin_name: param.username,
+		phone: param.phone,
+		password: param.password,
+		level: param.checkedRole[0] == '超级管理员' ? 2 : 1,
+		user_name: param.fullname,
+		remark: param.comment,
+    admin_power: '1,2,3,4,5,6',
+		// card_number: param.cardNumber
+	};
+  
+	return request({
+		url: '/admininsert.action',
+		method: 'post',
+		data
+	});
+};
+
+// 修改管理员
+export function modifyAccount(param) {
+	let data = {
+		id: param.id,
+		admin_name: param.username,
+		phone: param.phone,
+		password: param.password,
+		user_name: param.fullname,
+		level: param.checkedRole[0] == '超级管理员' ? 2 : 1,
+		remark: param.comment,
+    admin_power: '1,2,3,4,5,6',
+		// card_number: param.cardNumber
+	};
+	return request({
+		url: '/adminupdate.action',
+		method: 'post',
+		data
+	});
+};
+
+// 删除管理员
+export function deleteAccount(param) {
+	let data = new FormData();
+	data.append('id', param);
+	return request({
+		url: '/admindel.action',
+		method: 'post',
+		data
+	});
+};

+ 0 - 72
src/api/acl/permission.js

@@ -1,72 +0,0 @@
-import request from '@/utils/request'
-
-/* 
-权限管理相关的API请求函数
-*/
-const api_name = '/admin/acl/permission'
-
-export default {
-  
-  /* 
-  获取权限(菜单/功能)列表
-  */
-  getPermissionList() {
-    return request({
-      url: `${api_name}`,
-      method: 'get'
-    })
-  },
-  
-  /* 
-  删除一个权限项
-  */
-  removePermission(id) {
-    return request({
-      url: `${api_name}/remove/${id}`,
-      method: "delete"
-    })
-  },
-  
-  /* 
-  保存一个权限项
-  */
-  addPermission(permission) {
-    return request({
-      url: `${api_name}/save`,
-      method: "post",
-      data: permission
-    })
-  },
-
-  /* 
-  更新一个权限项
-  */
-  updatePermission(permission) {
-    return request({
-      url: `${api_name}/update`,
-      method: "put",
-      data: permission
-    })
-  },
-
-  /* 
-  查看某个角色的权限列表
-  */
-  toAssign(roleId) {
-    return request({
-      url: `${api_name}/toAssign/${roleId}`,
-      method: 'get'
-    })
-  },
-
-  /* 
-  给某个角色授权
-  */
-  doAssign(roleId, permissionId) {
-    return request({
-      url: `${api_name}/doAssign`,
-      method: "post",
-      params: {roleId, permissionId}
-    })
-  }
-}

+ 0 - 83
src/api/acl/role.js

@@ -1,83 +0,0 @@
-/* 
-角色管理相关的API请求函数
-*/
-import request from '@/utils/request'
-
-const api_name = '/admin/acl/role'
-
-export default {
-
-  /* 
-  获取角色分页列表(带搜索)
-  */
-  getPageList(page, limit, searchObj) {
-    return request({
-      url: `${api_name}/${page}/${limit}`,
-      method: 'get',
-      params: searchObj // url查询字符串或表单键值对
-    })
-  },
-
-  /* 
-  获取某个角色
-  */
-  getById(id) {
-    return request({
-      url: `${api_name}/get/${id}`,
-      method: 'get'
-    })
-  },
-
-  /* 
-  保存一个新角色
-  */
-  save(role) {
-    return request({
-      url: `${api_name}/save`,
-      method: 'post',
-      data: role
-    })
-  },
-
-  /* 
-  更新一个角色
-  */
-  updateById(role) {
-    return request({
-      url: `${api_name}/update`,
-      method: 'put',
-      data: role
-    })
-  },
-
-  /* 
-  获取一个角色的所有权限列表
-  */
-  getAssign(roleId) {
-    return request({
-      url: `${api_name}/toAssign/${roleId}`,
-      method: 'get'
-    })
-  },
-
-  /* 
-  删除某个角色
-  */
-  removeById(id) {
-    return request({
-      url: `${api_name}/remove/${id}`,
-      method: 'delete'
-    })
-  },
-
-  /* 
-  批量删除多个角色
-  */
-  removeRoles(ids) {
-    return request({
-      url: `${api_name}/batchRemove`,
-      method: 'delete',
-      data: ids
-    })
-  }
-}

+ 0 - 132
src/api/acl/user.js

@@ -1,132 +0,0 @@
-import request from '@/utils/request'
-
-const api_name = '/api/ihotel/hotelStaff'
-
-/*
-登陆
-*/
-export function login({ username, password }) {
-  return request({
-    url: '/admin/acl/index/login',
-    method: 'post',
-    data: { username, password }
-  })
-}
-
-/*
-获取用户信息(根据token)
-*/
-export function getInfo() {
-  return request({
-    url: '/admin/acl/index/info',
-    method: 'get'
-  })
-}
-
-/*
-登出
-*/
-export function logout() {
-  return request({
-    url: '/admin/acl/index/logout',
-    method: 'post'
-  })
-}
-
-/* 
-获取当前用户的菜单权限列表
-*/
-export function getMenu() {
-  return request('/admin/acl/index/menu')
-}
-
-
-/* 
-获取后台用户分页列表(带搜索)
-*/
-export function getPageList(page, limit, searchObj) {
-  return request({
-    url: `${api_name}/${page}/${limit}`,
-    method: 'get',
-    params: searchObj
-  })
-}
-
-/* 
-根据ID获取某个后台用户
-*/
-export function getById(id) {
-  return request({
-    url: `${api_name}/get/${id}`,
-    method: 'get'
-  })
-}
-
-/* 
-保存一个新的后台用户
-*/
-export function add(user) {
-  return request({
-    url: `${api_name}/save`,
-    method: 'post',
-    data: user
-  })
-}
-
-/* 
-更新一个后台用户
-*/
-export function update(user) {
-  return request({
-    url: `${api_name}/update`,
-    method: 'put',
-    data: user
-  })
-}
-
-/* 
-获取某个用户的所有角色
-*/
-export function getRoles(userId) {
-  return request({
-    url: `${api_name}/toAssign/${userId}`,
-    method: 'get'
-  })
-}
-
-/* 
-给某个用户分配角色
-roleId的结构: 字符串, 'rId1,rId2,rId3'
-*/
-export function assignRoles(userId, roleId) {
-  return request({
-    url: `${api_name}/doAssign`,
-    method: 'post',
-    params: {
-      userId,
-      roleId
-    }
-  })
-}
-
-/* 
-删除某个用户
-*/
-export function removeById(id) {
-  return request({
-    url: `${api_name}/remove/${id}`,
-    method: 'delete'
-  })
-}
-
-/* 
-批量删除多个用户
-ids的结构: ids是包含n个id的数组
-*/
-export function removeUsers(ids) {
-  return request({
-    url: `${api_name}/batchRemove`,
-    method: 'delete',
-    data: ids
-  })
-}

+ 0 - 59
src/api/api.js

@@ -1,59 +0,0 @@
-// import http from '../utils/http'
-import * as doorLock from "./doorLock";
-import * as fileServes from "./fileServes";
-import * as hotelOrder from "./hotelOrder";
-import * as hotelAdmin from "./hotelAdmin";
-import * as hotelStaff from "./hotelStaff";
-import * as houseType from "./houseType";
-import * as normalUser from "./normalUser";
-import * as room from "./room";
-import * as systemnotice from "./systemnotice";
-import * as systemSetup from "./systemSetup";
-import * as roomRealTimeStatu from "./roomRealTimeStatu";
-import * as roomThirdSetting from "./roomThirdSetting";
-import * as icCard from "./icCard";
-import * as fingerprint from "./fingerprint";
-import * as stat from "./stat";
-//
-/**
- *  @parms resquest 请求地址 例如:http://197.82.15.15:8088/request/...
- *  @param '/testIp'代表vue-cil中config,index.js中配置的代理
- */
-// let resquest = "/api/ihotel"
-
-// get请求
-// export function getListAPI(params) {
-//     return http.get(`${resquest}/getList.json`, params)
-// }
-
-// // post请求
-// export function postFormAPI(params) {
-//     return http.post(`${resquest}/postForm.json`, params)
-// }
-
-// // put 请求
-// export function putSomeAPI(params) {
-//     return http.put(`${resquest}/putSome.json`, params)
-// }
-// // delete 请求
-// export function deleteListAPI(params) {
-//     return http.delete(`${resquest}/deleteList.json`, params)
-// }
-
-export default {
-  doorLock, // 门锁
-  fileServes, // 文件服务
-  hotelOrder, // 酒店订单
-  hotelAdmin, // 酒店管理员
-  hotelStaff, // 酒店员工
-  houseType, // 房型
-  normalUser, // 普通用户
-  room, // 房间
-  systemnotice, // 系统通知
-  systemSetup, // 系统设置
-  roomRealTimeStatu, // 实时房态
-  roomThirdSetting, // 房间第三方平台设置
-  icCard, // IC卡
-  stat, // 统计报表
-  fingerprint // 指纹
-};

+ 0 - 17
src/api/doorLock.js

@@ -1,17 +0,0 @@
-import http from '../utils/http'
-let resquest = "/hotel/ihotel-api/ihotel/roomDoorLock"
-
-// 根据房间id查询密码锁
-export function roomDoorLockRoomId(roomId) {
-    return http.get(`${resquest}/room/${roomId}`)
-}
-
-// 根据订单id查询密码锁
-export function roomDoorLockOrderId(orderId) {
-    return http.get(`${resquest}/order/${orderId}`)
-}
-
-// 根据订单id下发密码锁
-export function sendPassword(Id) {
-    return http.get(`${resquest}/sendPassword/${Id}`)
-}

+ 0 - 7
src/api/fileServes.js

@@ -1,7 +0,0 @@
-import http from '../utils/http'
-let resquest = "/hotel/ihotel-api/ihotel"
-
-// 获取上传文件签名
-export function getListAPI(params) {
-    return http.get(`${resquest}/oss/aliyun/policy`, params)
-}

+ 0 - 31
src/api/fingerprint.js

@@ -1,31 +0,0 @@
-import http from "../utils/http";
-let resquest = "/hotel/ihotel-api/ihotel/condition/fingerprint";
-
-// fingerprint查询
-export function queryInfo(params) {
-  return http.get(`${resquest}/queryInfo/${params}`);
-}
-
-// IC卡查询-详情
-export function queryICInfoById(params) {
-  return http.get(`${resquest}/ic/queryICInfoById`, params);
-}
-
-// 指纹新增
-export function add(params) {
-  return http.post(`${resquest}/add`, params);
-}
-//  指纹修改  hotel/ihotel-api/ihotel/condition/fingerprint/update
-export function update(params) {
-  return http.post(`${resquest}/update`, params);
-}
-
-// 指纹解绑  hotel/ihotel-api/ihotel/condition/fingerprint/unbundFingerprint
-export function unbundIC(params) {
-  return http.get(`${resquest}/unbundFingerprint`, params);
-}
-
-// 指纹导出详情
-// export function downLoadICInfo(params) {
-//   return http.get(`${resquest}/downLoadICInfo`, params, "", "blob");
-// }

+ 0 - 32
src/api/hotelAdmin.js

@@ -1,32 +0,0 @@
-import http from '../utils/http'
-let resquest = "/hotel/ihotel-api/ihotel/hotelAdmin"
-
-// 管理员登录
-export function hotelStaffLogin(params) {
-    return http.post(`${resquest}/login`, params)
-}
-
-// 管理员列表
-export function hotelStaffList(params) {
-    return http.get(`${resquest}/list`, params)
-}
-
-// 新增管理员
-export function hotelStaffAdd(data) {
-    return http.post(`${resquest}/add`, data)
-}
-
-// 修改管理员
-export function hotelStaffUpdate(data) {
-    return http.put(`${resquest}/update`, data)
-}
-
-// 修改密码
-export function updatePassword(data) {
-    return http.put(`${resquest}/updatePassword`, data)
-}
-
-// 删除管理员
-export function hotelStaffDelete(data) {
-    return http.delete(`${resquest}/delete`, data)
-}

+ 0 - 71
src/api/hotelOrder.js

@@ -1,71 +0,0 @@
-import http from '../utils/http'
-let resquest = "/hotel/ihotel-api/ihotel/hotelOrder"
-let contentType = { 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8' }
-//  获取请求令牌
-export function hotelOrderToken(params) {
-    return http.get(`${resquest}/user/submit/token`, params)
-}
-
-//  确认订单    
-export function hotelOrderConfirm(params) {
-    return http.get(`${resquest}/user/order/confirm`, params)
-}
-
-//  提交订单
-export function hotelOrderSubmit(params) {
-    return http.post(`${resquest}/user/order/submit`, params)
-}
-
-//  订单列表【用户端】  
-export function hotelOrderUserPage(params) {
-    return http.get(`${resquest}/user/order/page`, params)
-}
-
-//  订单列表【管理端】
-export function hotelOrderAdminPage(params) {
-    return http.get(`${resquest}/admin/order/page`, params)
-}
-
-//  订单详情 【用户端】
-export function hotelOrderUserOrderId(orderId, params) {
-    return http.get(`${resquest}/user/order/${orderId}`, params)
-}
-
-//   获取订单支付参数
-export function hotelOrderOrderPay(orderId, params) {
-    return http.get(`${resquest}/user/order/pay/${orderId}`, params)
-}
-
-//   获取订单支付参数
-export function hotelOrderOrderBill(orderId, params) {
-    return http.get(`${resquest}/user/order/bill/${orderId}`, params)
-}
-
-//   导出订单【管理端】
-export function downOrder(params) {
-    return http.get(`${resquest}/admin/order/downOrder`, params, '', 'blob')
-}
-
-
-
-
-//  删除订单【管理端】
-export function hotelOrderAdminDelete(orderId, params) {
-    return http.delete(`${resquest}/admin/order/${orderId}`, params, contentType)
-}
-
-// 取消订单
-export function hotelOrdercancel(orderId, params) {
-    return http.put(`${resquest}/user/order/cancel/${orderId}`, params, contentType)
-}
-
-// 办理入住
-export function hotelOrderHold(orderId, params) {
-    return http.put(`${resquest}/user/order/hold/${orderId}`, params, contentType)
-}
-
-// 办理退房
-export function hotelOrderReturn(orderId, params) {
-    return http.put(`${resquest}/user/order/return/${orderId}`, params, contentType)
-}
-

+ 0 - 32
src/api/hotelStaff.js

@@ -1,32 +0,0 @@
-import http from "../utils/http";
-let resquest = "/hotel/ihotel-api/ihotel/ihotel/hotelStaff";
-
-// 员工列表
-export function hotelStaffList(params) {
-  return http.get(`${resquest}/list`, params);
-}
-
-// 员工信息
-export function hotelStaffInfo(id, params) {
-  return http.get(`${resquest}/info/${id}`, params);
-}
-
-// 新增员工
-export function hotelStaffSave(params) {
-  return http.post(`${resquest}/save`, params);
-}
-
-// 修改管理员
-export function hotelStaffUpdate(data) {
-  return http.put(`${resquest}/update`, data);
-}
-
-// 删除管理员
-export function hotelStaffDelete(data) {
-  return http.delete(`${resquest}/delete`, data);
-}
-
-// 员工类型和员工
-export function departList(params) {
-  return http.get(`${resquest}/departList`, params);
-}

+ 59 - 0
src/api/house.js

@@ -0,0 +1,59 @@
+import request from '@/utils/request'
+
+// 获取充值记录,表格数据
+export function getTableData(forData) {
+	let data = new FormData()
+	data.append('page', forData.page)
+	data.append('rows', forData.rows)
+	if (typeof forData.h_type != 'undefined') {
+		data.append('h_type', forData.h_type)
+	}
+	return request({
+		url: '/houselist.action',
+		method: 'post',
+		data
+	})
+}
+
+// 添加房型
+export function addHouseType(forData) {
+  let data = {
+  	h_type: forData.h_type,
+  	price: forData.price,
+  	number: forData.number
+  };
+
+	return request({
+		url: '/houseinsert.action',
+		method: 'post',
+		data
+	})
+}
+
+// 修改房型
+export function modifyHouseType(forData) {
+  let data = {
+    id: forData.id,
+  	h_type: forData.h_type,
+  	price: forData.price,
+  	number: forData.number
+  };
+
+	return request({
+		url: '/houseupdate.action',
+		method: 'post',
+		data
+	})
+}
+
+// 修改房型
+export function delHouseType(forData) {
+  let data = new FormData()
+  data.append('id', forData.id)
+
+	return request({
+		url: '/housedel.action',
+		method: 'post',
+		data
+	})
+}

+ 0 - 32
src/api/houseType.js

@@ -1,32 +0,0 @@
-import http from '../utils/http'
-let resquest = "/hotel/ihotel-api/ihotel/roomType"
-
-// 房型列表(客户端)
-export function roomTypeList(params) {
-    return http.get(`${resquest}/roomType/list`, params)
-}
-
-// 房型列表(管理端)
-export function roomTypePage(params) {
-    return http.get(`${resquest}/roomType/page`, params)
-}
-
-// 房型详细信息
-export function roomTypeInfo(params) {
-    return http.post(`${resquest}/info/{id}`, params)
-}
-
-// 新增房型
-export function roomTypeSave(params) {
-    return http.post(`${resquest}/save`, params)
-}
-
-// 修改房型
-export function roomTypeUpdate(params) {
-    return http.put(`${resquest}/update`, params)
-}
-
-// 删除房型
-export function roomTypeDelete(params) {
-    return http.delete(`${resquest}/delete`, params)
-}

+ 0 - 31
src/api/icCard.js

@@ -1,31 +0,0 @@
-import http from "../utils/http";
-let resquest = "/hotel/ihotel-api/ihotel/condition";
-
-// IC卡查询
-export function icqueryInfo(params) {
-  return http.get(`${resquest}/ic/queryInfo/${params}`);
-}
-
-// IC卡查询-详情
-export function queryICInfoById(params) {
-  return http.get(`${resquest}/ic/queryICInfoById`, params);
-}
-
-//  IC卡新增
-export function add(params) {
-  return http.post(`${resquest}/ic/add`, params);
-}
-//  IC卡修改
-export function update(params) {
-  return http.post(`${resquest}/ic/update`, params);
-}
-
-// IC卡解绑
-export function unbundIC(params) {
-  return http.get(`${resquest}/ic/unbundIC`, params);
-}
-
-// IC卡导出详情
-export function downLoadICInfo(params) {
-  return http.get(`${resquest}/downLoadICInfo`, params, "", "blob");
-}

+ 0 - 12
src/api/normalUser.js

@@ -1,12 +0,0 @@
-import http from '../utils/http'
-let resquest = "/hotel/ihotel-api/ihotel/hotelUser"
-
-// 微校授权回调地址
-export function hotelUserWX(params) {
-    return http.get(`${resquest}/weixiaoAuth`, params)
-}
-
-//  获取用户信息
-export function hotelUserInfo(params) {
-    return http.get(`${resquest}/userInfo`, params)
-}

+ 60 - 0
src/api/order.js

@@ -0,0 +1,60 @@
+import request from '@/utils/request'
+
+// 获取充值记录,表格数据
+export function getTableData(forData) {
+  let data = new FormData()
+  data.append('page', forData.page)
+  data.append('rows', forData.rows)
+  if (typeof forData.order_name_phone != 'undefined') {
+    data.append('order_name_phone', forData.order_name_phone)
+  }
+  if (typeof forData.start_time != 'undefined') {
+    data.append('start_time', forData.start_time)
+  }
+  if (typeof forData.end_time != 'undefined') {
+    data.append('end_time', forData.end_time)
+  }
+  if (typeof forData.status != 'undefined') {
+    data.append('status', forData.status)
+  }
+  return request({
+    url: '/booklist.action',
+    method: 'post',
+    data
+  })
+}
+
+// 核销   退款    退房
+export function collate_refund_checkout(forData) {
+  let data = new FormData()
+  data.append('id', forData.id)
+  data.append('status', forData.status)
+  return request({
+    url: '/bookoperate.action',
+    method: 'post',
+    data
+  })
+}
+
+// 下载
+export function downloadExcel(forData) {
+  let data = new FormData()
+  if (typeof forData.order_name_phone != 'undefined') {
+    data.append('order_name_phone', forData.order_name_phone)
+  }
+  if (typeof forData.start_time != 'undefined') {
+    data.append('start_time', forData.start_time)
+  }
+  if (typeof forData.end_time != 'undefined') {
+    data.append('end_time', forData.end_time)
+  }
+  if (typeof forData.status != 'undefined') {
+    data.append('status', forData.status)
+  }
+  // console.log(forData);
+  return request({
+    url: '/bookto_excel.action',
+    method: 'post',
+    data
+  })
+}

+ 0 - 27
src/api/room.js

@@ -1,27 +0,0 @@
-import http from '../utils/http'
-let resquest = "/hotel/ihotel-api/ihotel/room"
-
-// 房间列表(分页)
-export function roomPage(params) {
-    return http.get(`${resquest}/page`, params)
-}
-
-// 房间列表(分页分组)
-export function roomPageGroup(params) {
-    return http.get(`${resquest}/page/group`, params)
-}
-
-// 新增房间
-export function roomSave(params) {
-    return http.post(`${resquest}/save`, params)
-}
-
-// 修改房间
-export function roomUpdate(params) {
-    return http.put(`${resquest}/update`, params)
-}
-
-// 删除房间
-export function roomDelete(params) {
-    return http.delete(`${resquest}/delete`, params)
-}

+ 0 - 25
src/api/roomRealTimeStatu.js

@@ -1,25 +0,0 @@
-import http from "../utils/http";
-let resquest = "/hotel/ihotel-api/ihotel/roomRealTimeStatu";
-
-//  房态信息
-export function realData(params) {
-  return http.get(`${resquest}/realData/${params}`);
-}
-
-// 脏房修改为空闲房间   /hotel/ihotel-api/ihotel/roomRealTimeStatu/clean/cleanByStatuId
-let ContentType = {
-  "Content-Type": "application/x-www-form-urlencoded;charset=utf-8"
-};
-export function clean(params) {
-  return http.post(`${resquest}/clean/cleanByStatuId`, params);
-}
-
-// 锁定房间  /hotel/ihotel-api/ihotel/roomRealTimeStatu/lock
-export function lock(params) {
-  return http.put(`${resquest}/lock`, params);
-}
-
-// 房间转为脏房
-export function toDirty(params) {
-  return http.put(`${resquest}/toDirty`, params);
-}

+ 0 - 17
src/api/roomThirdSetting.js

@@ -1,17 +0,0 @@
-import http from '../utils/http'
-let resquest = "/hotel/ihotel-api/ihotel/roomThirdSetting"
-
-//  根据房间id查询
-export function settingId(params) {
-    return http.get(`${resquest}/setting/${params}`)
-}
-
-//  电控制
-export function changeElectric(roomId, operType) {
-    return http.get(`${resquest}/changeElectric/${roomId}/${operType}`)
-}
-
-// 修改房间第三方平台设置
-export function Updata(params) {
-    return http.post(`${resquest}/update`, params)
-}

+ 0 - 13
src/api/stat.js

@@ -1,13 +0,0 @@
-import http from '../utils/http'
-let resquest = "/hotel/ihotel-api/ihotel/report"
-
-// 12.1. 查询统计报表数据【管理端】
-export function queryReport(params) {
-    return http.get(`${resquest}/queryReport`, params)
-}
-
-//  导出报表【管理端】
-export function downLoadReport(params) {
-    return http.get(`${resquest}/downLoadReport`, params, '', 'blob')
-}
-

+ 16 - 0
src/api/systemSet.js

@@ -0,0 +1,16 @@
+import request from '@/utils/request'
+
+export function updateSet(data) {
+	return request({
+		url: '/configupdate.action',
+		method: 'post',
+		data
+	})
+}
+
+export function getSet() {
+	return request({
+		url: '/configlist.action',
+		method: 'post'
+	})
+}

+ 0 - 13
src/api/systemSetup.js

@@ -1,13 +0,0 @@
-import http from '../utils/http'
-let resquest = "/hotel/ihotel-api/ihotel/systemSetting"
-
-// 获取系统设置
-export function systemSettingInfo(params) {
-    return http.get(`${resquest}/info`, params)
-}
-
-// 修改系统设置
-export function systemnoticeUpdate(params) {
-    return http.put(`${resquest}/update`, params)
-}
-

+ 0 - 17
src/api/systemnotice.js

@@ -1,17 +0,0 @@
-import http from '../utils/http'
-let resquest = "/hotel/ihotel-api/ihotel/systemNotice"
-
-// 通知列表
-export function systemnoticeList(params) {
-    return http.get(`${resquest}/list`, params)
-}
-
-// 标记为已读
-export function systemnoticeRead(params) {
-    return http.put(`${resquest}/read`, params)
-}
-
-// 删除通知
-export function systemnoticeDelete(params) {
-    return http.delete(`${resquest}/delete`, params)
-}

+ 30 - 0
src/api/user.js

@@ -0,0 +1,30 @@
+import request from '@/utils/request'
+
+export function login(forData) {
+	let data = new FormData()
+	data.append('admin_name', forData.username.trim())
+	data.append('password', forData.password.trim())
+
+	return request({
+		url: '/adminlogin.action',
+		method: 'post',
+		data
+	})
+}
+
+// export function getInfo(token) {
+// 	return request({
+// 		url: '/airManage/info',
+// 		method: 'get',
+// 		params: {
+// 			token
+// 		}
+// 	})
+// }
+
+// export function logout() {
+// 	return request({
+// 		url: '/airManage/adminloginout.action',
+// 		method: 'post'
+// 	})
+// }

BIN
src/assets/404_images/404.png


BIN
src/assets/404_images/404_cloud.png


File diff suppressed because it is too large
+ 0 - 1
src/assets/icons/svg/account-active.svg


File diff suppressed because it is too large
+ 0 - 1
src/assets/icons/svg/account.svg


File diff suppressed because it is too large
+ 0 - 1
src/assets/icons/svg/edit.svg


File diff suppressed because it is too large
+ 0 - 1
src/assets/icons/svg/error.svg


File diff suppressed because it is too large
+ 0 - 1
src/assets/icons/svg/home-active.svg


File diff suppressed because it is too large
+ 0 - 1
src/assets/icons/svg/home.svg


File diff suppressed because it is too large
+ 0 - 1
src/assets/icons/svg/item-logo.svg


File diff suppressed because it is too large
+ 0 - 1
src/assets/icons/svg/order-active.svg


File diff suppressed because it is too large
+ 0 - 1
src/assets/icons/svg/order.svg


File diff suppressed because it is too large
+ 0 - 1
src/assets/icons/svg/quit.svg


File diff suppressed because it is too large
+ 0 - 1
src/assets/icons/svg/sousuo.svg


File diff suppressed because it is too large
+ 0 - 1
src/assets/icons/svg/staff-active.svg


File diff suppressed because it is too large
+ 0 - 1
src/assets/icons/svg/staff.svg


File diff suppressed because it is too large
+ 0 - 1
src/assets/icons/svg/stat-active.svg


File diff suppressed because it is too large
+ 0 - 1
src/assets/icons/svg/stat.svg


File diff suppressed because it is too large
+ 0 - 1
src/assets/icons/svg/system-active.svg


File diff suppressed because it is too large
+ 0 - 1
src/assets/icons/svg/system.svg


File diff suppressed because it is too large
+ 0 - 1
src/assets/icons/svg/tuifang.svg


File diff suppressed because it is too large
+ 0 - 1
src/assets/icons/svg/xiaoxizhongxin.svg


BIN
src/assets/images/bg.png


BIN
src/assets/images/eye.png


BIN
src/assets/images/eye_close.png


BIN
src/assets/images/password.png


BIN
src/assets/images/user.png


+ 0 - 0
src/assets/scss/variable.scss


+ 89 - 0
src/components/Breadcrumb/index.vue

@@ -0,0 +1,89 @@
+<template>
+	<el-breadcrumb class="app-breadcrumb" separator="/">
+		<transition-group name="breadcrumb">
+			<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
+				<span v-if="item.redirect==='noRedirect'||index==levelList.length-1"
+					class="no-redirect">{{ item.meta.title }}</span>
+				<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
+			</el-breadcrumb-item>
+		</transition-group>
+	</el-breadcrumb>
+</template>
+
+<script>
+	import pathToRegexp from 'path-to-regexp'
+
+	export default {
+		data() {
+			return {
+				levelList: null
+			}
+		},
+		watch: {
+			$route() {
+				this.getBreadcrumb()
+			}
+		},
+		created() {
+			this.getBreadcrumb()
+		},
+		methods: {
+			getBreadcrumb() {
+				// only show routes with meta.title
+				let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
+				const first = matched[0]
+
+				if (!this.isDashboard(first)) {
+					matched = [{
+						path: '/dashboard',
+						meta: {
+							title: 'Dashboard'
+						}
+					}].concat(matched)
+				}
+
+				this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
+			},
+			isDashboard(route) {
+				const name = route && route.name
+				if (!name) {
+					return false
+				}
+				return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
+			},
+			pathCompile(path) {
+				// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
+				const {
+					params
+				} = this.$route
+				var toPath = pathToRegexp.compile(path)
+				return toPath(params)
+			},
+			handleLink(item) {
+				const {
+					redirect,
+					path
+				} = item
+				if (redirect) {
+					this.$router.push(redirect)
+					return
+				}
+				this.$router.push(this.pathCompile(path))
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.app-breadcrumb.el-breadcrumb {
+		display: inline-block;
+		font-size: 14px;
+		line-height: 50px;
+		margin-left: 8px;
+
+		.no-redirect {
+			color: #97a8be;
+			cursor: text;
+		}
+	}
+</style>

+ 40 - 0
src/components/Hamburger/index.vue

@@ -0,0 +1,40 @@
+<template>
+	<div style="padding: 0 15px;" @click="toggleClick">
+		<svg :class="{'is-active':isActive}" class="hamburger" viewBox="0 0 1024 1024"
+			xmlns="" width="64" height="64">
+			<path
+				d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" />
+		</svg>
+	</div>
+</template>
+
+<script>
+	export default {
+		name: 'Hamburger',
+		props: {
+			isActive: {
+				type: Boolean,
+				default: false
+			}
+		},
+		methods: {
+			toggleClick() {
+				this.$emit('toggleClick')
+			}
+		}
+	}
+</script>
+
+<style scoped>
+	.hamburger {
+		display: inline-block;
+		vertical-align: middle;
+		width: 32;
+		height: 32px;
+		margin-top: 28px;
+	}
+
+	.hamburger.is-active {
+		transform: rotate(180deg);
+	}
+</style>

+ 40 - 59
src/components/SvgIcon/index.vue

@@ -1,81 +1,62 @@
 <template>
-  <div class="icon-wrapper" :style="wd">
-    <svg class="icon" aria-hidden="true" :style="wd">
-      <use :xlink:href="iconName"></use>
-    </svg>
-  </div>
+  <div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
+  <svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
+    <use :xlink:href="iconName" />
+  </svg>
 </template>
- 
+
 <script>
-// 引入从iconfont 下载的symbox文件
-// import '@/assets/icons/iconfont-svg.js'
+// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
+import { isExternal } from '@/utils/validate'
 
-// 引入本地的svg文件
-// 定义一个加载目录的函数
-const requireAll = (requireContext) =>
-  requireContext.keys().map(requireContext);
-const req = require.context("@/assets/icons/svg", false, /\.svg$/);
-// 加载目录下的所有的 svg 文件
-requireAll(req);
-// console.log('I: 加载svg文件:', req.keys())
 export default {
-  name: "IconSvg",
+  name: 'SvgIcon',
   props: {
-    name: String,
-    prefix: {
+    iconClass: {
       type: String,
-      default: "icon-",
-    },
-    W: {
-      type: Number,
-      default: 28,
-    },
-    H: {
-      type: Number,
-      default: 28,
+      required: true
     },
+    className: {
+      type: String,
+      default: ''
+    }
   },
-  mounted() {},
   computed: {
+    isExternal() {
+      return isExternal(this.iconClass)
+    },
     iconName() {
-      let name = `#${this.prefix}${this.name}`;
-      return name;
+      return `#icon-${this.iconClass}`
     },
-    wd() {
-      const style = { width: this.W + "px", height: this.H + "px" };
-      return style;
+    svgClass() {
+      if (this.className) {
+        return 'svg-icon ' + this.className
+      } else {
+        return 'svg-icon'
+      }
     },
-  },
-};
+    styleExternalIcon() {
+      return {
+        mask: `url(${this.iconClass}) no-repeat 50% 50%`,
+        '-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
+      }
+    }
+  }
+}
 </script>
- 
+
 <style scoped>
-/*.icon-wrapper {
-  display: inline-block;
-}
-.icon {
-  width: 100%;
-  height: 100%;
+.svg-icon {
+  width: 1em;
+  height: 1em;
   vertical-align: -0.15em;
   fill: currentColor;
   overflow: hidden;
-}*/
-
-.icon-wrapper {
-  /* Using currentColor above lets
-  us use `color` for changing the color
-  of our icons: */
-  color: red;
-
-  /* The width and height of the SVG
-  was previously set to 1em.
-  This allows us to use `font-size`
-  to change the size of our icon: */
 }
 
-.icon {
+.svg-external-icon {
+  background-color: currentColor;
+  mask-size: cover!important;
   display: inline-block;
-  color: #444444;
-  fill: currentColor;
 }
-</style>
+</style>

BIN
src/icons/images/index/title_icon.png


BIN
src/icons/images/index/yewu.png


BIN
src/icons/images/index/yujing.png


BIN
src/icons/images/index/zhuangtai.png


BIN
src/icons/images/index/zoushi.png


BIN
src/icons/images/login/login_bg.png


+ 0 - 0
src/icons/images/login/login_form_bg.png


Some files were not shown because too many files changed in this diff