Browse Source

最新一版加集成页面

GuoYuFu123 6 years ago
parent
commit
3ce8c6e1a7
67 changed files with 5457 additions and 1028 deletions
  1. 88 32
      README.md
  2. 24 20
      build/build.js
  3. 35 33
      build/check-versions.js
  4. 73 74
      build/utils.js
  5. 13 15
      build/vue-loader.conf.js
  6. 6 4
      build/webpack.base.conf.js
  7. 69 71
      build/webpack.dev.conf.js
  8. 112 118
      build/webpack.prod.conf.js
  9. 1 3
      config/dev.env.js
  10. 1 2
      config/prod.env.js
  11. 0 2
      index.html
  12. 10 0
      src/api/database/hbase.js
  13. 12 0
      src/api/database/redis.js
  14. 99 0
      src/api/framework.js
  15. 100 0
      src/api/httputils.js
  16. 21 0
      src/api/system/role.js
  17. 15 0
      src/api/system/user.js
  18. BIN
      src/assets/logo-small.jpg
  19. BIN
      src/assets/logo.jpg
  20. BIN
      src/assets/logo.png
  21. 38 0
      src/components/HelloWorld.vue
  22. 1 1
      src/components/config_point/step3_edit/split_handle.vue
  23. 154 174
      src/data/menus.js
  24. 32 0
      src/demo/demo-menus.js
  25. 53 0
      src/demo/demo-routes.js
  26. 131 0
      src/demo/test/fugy/Dialog.vue
  27. 167 0
      src/demo/test/fugy/Step3.vue
  28. 164 0
      src/demo/test/fugy/Step4.vue
  29. 1730 0
      src/demo/test/fugy/Tab1.vue
  30. 68 0
      src/demo/test/fugy/Tab2.vue
  31. 87 0
      src/demo/test/fugy/Tab3.vue
  32. 20 0
      src/demo/test/fugy/index.less
  33. 35 0
      src/demo/test/fugy/index.vue
  34. 15 0
      src/demo/test/wangsw/index.vue
  35. 100 0
      src/demo/test/zhulz/alarmCode.vue
  36. 426 0
      src/demo/test/zhulz/index.vue
  37. 99 0
      src/demo/test/zhulz/manageNote.vue
  38. 152 0
      src/demo/views/form/FormPageDemo.vue
  39. 122 0
      src/demo/views/table/TablePageDemo.vue
  40. 53 0
      src/framework/components/BasePagination.vue
  41. 171 13
      src/framework/layout/Login.vue
  42. 10 6
      src/framework/layout/Main.vue
  43. 10 14
      src/framework/layout/PageHeader.vue
  44. 29 31
      src/framework/layout/PageSidebar.vue
  45. 5 46
      src/framework/layout/layout-store.js
  46. 12 17
      src/plugins/components.js
  47. 110 77
      src/framework/style/layout.scss
  48. 68 33
      src/framework/style/theme.scss
  49. 0 14
      src/utils/basicutils.js
  50. 0 0
      src/framework/utils/storage.js
  51. 3 7
      src/main.js
  52. 0 17
      src/router/demo.js
  53. 7 7
      src/router/index.js
  54. 11 7
      src/router/sagacloud.js
  55. 4 10
      src/store/index.js
  56. 0 28
      src/store/modules/alarm.js
  57. 0 29
      src/store/modules/proMess.js
  58. 0 42
      src/store/modules/project.js
  59. 42 38
      src/utils/authutils.js
  60. 0 40
      src/views/system/auth/index.vue
  61. 0 3
      src/views/system/pwd/ChangePwd.vue
  62. 78 0
      src/views/system/role/RoleEdit.vue
  63. 87 0
      src/views/system/role/RoleList.vue
  64. 170 0
      src/views/system/role/RoleManage.vue
  65. 132 0
      src/views/system/role/eleTreeUtils.js
  66. 100 0
      src/views/system/user/UserAdd.vue
  67. 82 0
      src/views/system/user/UserList.vue

+ 88 - 32
README.md

@@ -5,53 +5,110 @@
 ## Build Setup
 ## Build Setup
 
 
 ```bash
 ```bash
-# install dependencies
 npm install
 npm install
 npm install vuex axios element-ui echarts font-awesome
 npm install vuex axios element-ui echarts font-awesome
+npm install less less-loader node-sass sass-loader --save-dev
 
 
 # serve with hot reload at localhost:8080
 # serve with hot reload at localhost:8080
 npm run dev
 npm run dev
-npm install less less-loader node-sass sass-loader --save-dev
-
 # build for production with minification
 # build for production with minification
 npm run build
 npm run build
-
 # build for production and view the bundle analyzer report
 # build for production and view the bundle analyzer report
 npm run build --report
 npm run build --report
 ```
 ```
 
 
-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).
+## 项目结构说明
 
 
 #### 目录结构
 #### 目录结构
 
 
 ```
 ```
-├─api                       服务端接口API
-│
-├─components                通用组件
-│
-├─data                      静态数据
-│      menus.js             页面菜单文件,在这里新增菜单
+│  .editorconfig                        # 格式化配置,修改缩进为4
+│  index.html                           # 修改页面title
+│  package.json                         # 包
+│  README.md                            # 说明文档
-├─framework                 页面框架, 不用修改
+├─build                                 # 不变
-├─plugins                   通用插件
+├─config
+│      dev.env.js                       # 开发环境变量
+│      index.js                         # 设置代理
+│      prod.env.js                      # 生产环境变量
-├─router                    路由
-│      index.js
-│      sagacloud.js         业务路由文件,在这里新增路由
-│
-├─store                     VUEX
-│      index.js
-│
-├─utils                     通用工具类
-│      authutils.js         认证工具, 不要修改
-│      basicutils.js
-│      httputils.js
-│      storage.js
-│
-└─views                     业务视图主目录, 这里创建新视图
-    ├─dasboard
-    └─system
+├─src
+│  ├─api                                # 业务逻辑api, http的请求都放在这里
+│  │  |─framework.js                    # 框架预留接口,实现登录,权限校验等功能
+│  │  └─httputils.js                    # http 工具类
+│  ├─assets                             # 静态资源, 替换logo图片
+│  ├─components                         # 业务相关组件
+│  ├─data                               # 业务相关静态数据
+│  │      menus.js                      # 菜单数据
+│  ├─demo                               # Demo主目录
+│  │  │  demo-menus.js                  # Demo按钮
+│  │  │  demo-routes.js                 # Demo路由
+│  │  └─views                           # Demo页面
+│  ├─framework                          # 框架主目录
+│  │  ├─components                      # 业务无关组件
+│  │  │
+│  │  ├─demo                            # Demo主目录
+│  │  │  │  demo-menus.js               # Demo按钮
+│  │  │  │  demo-routes.js              # Demo路由
+│  │  │  └─views                        # Demo页面
+│  │  │
+│  │  ├─layout                          # 框架主目录
+│  │  │      layout-store.js            # 框架状态定义
+│  │  │      Login.vue                  # 登录页
+│  │  │      Main.vue                   # 框架主页
+│  │  │      PageHeader.vue             # 顶部栏
+│  │  │      PageSidebar.vue            # 左侧菜单栏
+│  │  │
+│  │  ├─plugins                         # 插件,业务无关
+│  │  │      components.js
+│  │  ├─style                           # 样式
+│  │  │
+│  │  ├─template                        # 页面模板
+│  │  │      TablePageTemplate.vue
+│  │  │
+│  │  └─utils                           # 工具类,业务无关
+│  │
+│  ├─router                             # 主路由
+│  │      index.js
+│  │      system.js
+│  │
+│  ├─store                              # vuex
+│  │      index.js
+│  │
+│  └─views                              # 业务页面主路径
+|
+└─static
+        .gitkeep
+```
+
+#### /api/framework.js
+
+必须实现以下方法
+
+```
+export default {
+
+    // 路由拦截
+    routerBeforeEach: async function(to, from, next){},
+
+    // 获取左侧菜单数据
+    getMenus: function(permissions){},
+
+    // 跳转到登录页面
+    toLoginPage: function(){},
+
+    // 登录接口
+    login: function(username, password){}
+
+    // 加载当前登录用户信息
+    loadUserInfo: function(){},
+
+    // 退出登录
+    toLogout: function(){}
+}
+
 ```
 ```
 
 
 #### 工具类说明
 #### 工具类说明
@@ -63,10 +120,9 @@ For a detailed explanation on how things work, check out the [guide](http://vuej
     indexInArray(arr, key, val)        // 找出数组arr中第一个属性key的值等于val的元素的下标
     indexInArray(arr, key, val)        // 找出数组arr中第一个属性key的值等于val的元素的下标
     itemInArray(arr, key, val)         // 找出数组arr中第一个属性key的值等于val的元素
     itemInArray(arr, key, val)         // 找出数组arr中第一个属性key的值等于val的元素
     deleteInArray(arr, key, val)       // 从数组中将属性key的值等于val的所有元素删除
     deleteInArray(arr, key, val)       // 从数组中将属性key的值等于val的所有元素删除
-    hasPermission(promiseStr)          //判断该用户的权限是否具有某些权限
 ```
 ```
 
 
-/src/utils/httputils.js // 一般在服务端接口 API 中使用,不建议在别的地方使用,有授权标记
+/src/api/httputils.js // 一般在服务端接口 API 中使用,不建议在别的地方使用,有授权标记
 
 
 ```
 ```
     getCookie(name)                    // 获取cookie值
     getCookie(name)                    // 获取cookie值
@@ -85,5 +141,5 @@ For a detailed explanation on how things work, check out the [guide](http://vuej
 #### 设置面包屑方法
 #### 设置面包屑方法
 
 
 ```
 ```
-    this.$store.dispatch('setBreadcrumb', [{ label: 'Demo' }, { label: 'Form' }])
+在路由router中配置meta.breadcrumbs,在进入路由页面时会自动解析为面包屑
 ```
 ```

+ 24 - 20
build/build.js

@@ -15,27 +15,31 @@ const spinner = ora('building for production...')
 spinner.start()
 spinner.start()
 
 
 rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
 rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
-  if (err) throw err
-  webpack(webpackConfig, (err, stats) => {
-    spinner.stop()
     if (err) throw err
     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')
+    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)
-    }
+        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'
-    ))
-  })
+        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"
+            )
+        )
+    })
 })
 })

+ 35 - 33
build/check-versions.js

@@ -4,51 +4,53 @@ const semver = require('semver')
 const packageConfig = require('../package.json')
 const packageConfig = require('../package.json')
 const shell = require('shelljs')
 const shell = require('shelljs')
 
 
-function exec (cmd) {
-  return require('child_process').execSync(cmd).toString().trim()
+function exec(cmd) {
+    return require('child_process')
+        .execSync(cmd)
+        .toString()
+        .trim()
 }
 }
 
 
 const versionRequirements = [
 const versionRequirements = [
-  {
-    name: 'node',
-    currentVersion: semver.clean(process.version),
-    versionRequirement: packageConfig.engines.node
-  }
+    {
+        name: 'node',
+        currentVersion: semver.clean(process.version),
+        versionRequirement: packageConfig.engines.node
+    }
 ]
 ]
 
 
 if (shell.which('npm')) {
 if (shell.which('npm')) {
-  versionRequirements.push({
-    name: 'npm',
-    currentVersion: exec('npm --version'),
-    versionRequirement: packageConfig.engines.npm
-  })
+    versionRequirements.push({
+        name: 'npm',
+        currentVersion: exec('npm --version'),
+        versionRequirement: packageConfig.engines.npm
+    })
 }
 }
 
 
-module.exports = function () {
-  const warnings = []
+module.exports = function() {
+    const warnings = []
 
 
-  for (let i = 0; i < versionRequirements.length; i++) {
-    const mod = versionRequirements[i]
+    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 (!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()
+    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)
-    }
+        for (let i = 0; i < warnings.length; i++) {
+            const warning = warnings[i]
+            console.log('  ' + warning)
+        }
 
 
-    console.log()
-    process.exit(1)
-  }
+        console.log()
+        process.exit(1)
+    }
 }
 }

+ 73 - 74
build/utils.js

@@ -4,98 +4,97 @@ const config = require('../config')
 const ExtractTextPlugin = require('extract-text-webpack-plugin')
 const ExtractTextPlugin = require('extract-text-webpack-plugin')
 const packageConfig = require('../package.json')
 const packageConfig = require('../package.json')
 
 
-exports.assetsPath = function (_path) {
-  const assetsSubDirectory = process.env.NODE_ENV === 'production'
-    ? config.build.assetsSubDirectory
-    : config.dev.assetsSubDirectory
+exports.assetsPath = function(_path) {
+    const assetsSubDirectory =
+        process.env.NODE_ENV === 'production' ? config.build.assetsSubDirectory : config.dev.assetsSubDirectory
 
 
-  return path.posix.join(assetsSubDirectory, _path)
+    return path.posix.join(assetsSubDirectory, _path)
 }
 }
 
 
-exports.cssLoaders = function (options) {
-  options = options || {}
+exports.cssLoaders = function(options) {
+    options = options || {}
 
 
-  const cssLoader = {
-    loader: 'css-loader',
-    options: {
-      sourceMap: options.sourceMap
+    const cssLoader = {
+        loader: 'css-loader',
+        options: {
+            sourceMap: options.sourceMap
+        }
     }
     }
-  }
 
 
-  const postcssLoader = {
-    loader: 'postcss-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
-        })
-      })
+    // 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)
+        }
     }
     }
 
 
-    // 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')
     }
     }
-  }
-
-  // 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)
 // 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.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 = () => {
 exports.createNotifierCallback = () => {
-  const notifier = require('node-notifier')
+    const notifier = require('node-notifier')
 
 
-  return (severity, errors) => {
-    if (severity !== 'error') return
+    return (severity, errors) => {
+        if (severity !== 'error') return
 
 
-    const error = errors[0]
-    const filename = error.file && error.file.split('!').pop()
+        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')
-    })
-  }
+        notifier.notify({
+            title: packageConfig.name,
+            message: severity + ': ' + error.name,
+            subtitle: filename || '',
+            icon: path.join(__dirname, 'logo.png')
+        })
+    }
 }
 }

+ 13 - 15
build/vue-loader.conf.js

@@ -2,21 +2,19 @@
 const utils = require('./utils')
 const utils = require('./utils')
 const config = require('../config')
 const config = require('../config')
 const isProduction = process.env.NODE_ENV === 'production'
 const isProduction = process.env.NODE_ENV === 'production'
-const sourceMapEnabled = isProduction
-  ? config.build.productionSourceMap
-  : config.dev.cssSourceMap
+const sourceMapEnabled = isProduction ? config.build.productionSourceMap : config.dev.cssSourceMap
 
 
 module.exports = {
 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'
-  }
+    loaders: utils.cssLoaders({
+        sourceMap: sourceMapEnabled,
+        extract: isProduction
+    }),
+    cssSourceMap: sourceMapEnabled,
+    cacheBusting: config.dev.cacheBusting,
+    transformToRequire: {
+        video: ['src', 'poster'],
+        source: 'src',
+        img: 'src',
+        image: 'xlink:href'
+    }
 }
 }

+ 6 - 4
build/webpack.base.conf.js

@@ -19,8 +19,9 @@ module.exports = {
     output: {
     output: {
         path: config.build.assetsRoot,
         path: config.build.assetsRoot,
         filename: '[name].js',
         filename: '[name].js',
-        publicPath: process.env.NODE_ENV === 'production' ?
-            config.build.assetsPublicPath : config.dev.assetsPublicPath
+        publicPath: process.env.NODE_ENV === 'production'
+            ? config.build.assetsPublicPath
+            : config.dev.assetsPublicPath
     },
     },
     resolve: {
     resolve: {
         extensions: ['.js', '.vue', '.json'],
         extensions: ['.js', '.vue', '.json'],
@@ -38,7 +39,8 @@ module.exports = {
         })
         })
     ],
     ],
     module: {
     module: {
-        rules: [{
+        rules: [
+            {
                 test: /\.vue$/,
                 test: /\.vue$/,
                 loader: 'vue-loader',
                 loader: 'vue-loader',
                 options: vueLoaderConfig
                 options: vueLoaderConfig
@@ -86,4 +88,4 @@ module.exports = {
         tls: 'empty',
         tls: 'empty',
         child_process: 'empty'
         child_process: 'empty'
     }
     }
-}
+}

+ 69 - 71
build/webpack.dev.conf.js

@@ -14,82 +14,80 @@ const HOST = process.env.HOST
 const PORT = process.env.PORT && Number(process.env.PORT)
 const PORT = process.env.PORT && Number(process.env.PORT)
 
 
 const devWebpackConfig = merge(baseWebpackConfig, {
 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,
+    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') },
-      ],
+    // 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') }]
+        },
+        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
+        }
     },
     },
-    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: ['.*']
-      }
-    ])
-  ]
+    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) => {
 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
+    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: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
-        },
-        onErrors: config.dev.notifyOnErrors
-        ? utils.createNotifierCallback()
-        : undefined
-      }))
+            // Add FriendlyErrorsPlugin
+            devWebpackConfig.plugins.push(
+                new FriendlyErrorsPlugin({
+                    compilationSuccessInfo: {
+                        messages: [
+                            `Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`
+                        ]
+                    },
+                    onErrors: config.dev.notifyOnErrors ? utils.createNotifierCallback() : undefined
+                })
+            )
 
 
-      resolve(devWebpackConfig)
-    }
-  })
+            resolve(devWebpackConfig)
+        }
+    })
 })
 })

+ 112 - 118
build/webpack.prod.conf.js

@@ -14,132 +14,126 @@ const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
 const env = require('../config/prod.env')
 const env = require('../config/prod.env')
 
 
 const webpackConfig = merge(baseWebpackConfig, {
 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: 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
-    }),
+    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: 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: ['.*']
-      }
-    ])
-  ]
+        // copy custom static assets
+        new CopyWebpackPlugin([
+            {
+                from: path.resolve(__dirname, '../static'),
+                to: config.build.assetsSubDirectory,
+                ignore: ['.*']
+            }
+        ])
+    ]
 })
 })
 
 
 if (config.build.productionGzip) {
 if (config.build.productionGzip) {
-  const CompressionWebpackPlugin = require('compression-webpack-plugin')
+    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
-    })
-  )
+    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) {
 if (config.build.bundleAnalyzerReport) {
-  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
-  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
+    const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
+    webpackConfig.plugins.push(new BundleAnalyzerPlugin())
 }
 }
 
 
 module.exports = webpackConfig
 module.exports = webpackConfig

+ 1 - 3
config/dev.env.js

@@ -3,7 +3,5 @@ const merge = require('webpack-merge')
 const prodEnv = require('./prod.env')
 const prodEnv = require('./prod.env')
 
 
 module.exports = merge(prodEnv, {
 module.exports = merge(prodEnv, {
-    NODE_ENV: '"development"',
-    // SSO_SERVER: '"http://192.168.20.101:8004"'
-    SSO_SERVER: '"http://sso.sagacloud.cn"'
+    NODE_ENV: '"development"'
 })
 })

+ 1 - 2
config/prod.env.js

@@ -1,5 +1,4 @@
 'use strict'
 'use strict'
 module.exports = {
 module.exports = {
-    NODE_ENV: '"production"',
-    SSO_SERVER: '"http://sso.sagacloud.cn"'
+    NODE_ENV: '"production"'
 }
 }

+ 0 - 2
index.html

@@ -4,8 +4,6 @@
     <meta charset="utf-8" />
     <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width,initial-scale=1.0" />
     <meta name="viewport" content="width=device-width,initial-scale=1.0" />
     <title>sagacloud-admin</title>
     <title>sagacloud-admin</title>
-    <link rel="stylesheet" href="//at.alicdn.com/t/font_646072_j1rtd99vj8.css">
-    <link href='//at.alicdn.com/t/font_1112731_cpdyeyhpqk.css'>
   </head>
   </head>
   <body>
   <body>
     <div id="app"></div>
     <div id="app"></div>

+ 10 - 0
src/api/database/hbase.js

@@ -0,0 +1,10 @@
+import httputils from '@/utils/httputils'
+export default {
+    tables() {
+        return httputils.getJson('/admin/hbase/tables')
+    },
+
+    query(criteria) {
+        return httputils.postJson('/admin/hbase/query', criteria)
+    }
+}

+ 12 - 0
src/api/database/redis.js

@@ -0,0 +1,12 @@
+import httputils from '@/utils/httputils'
+export default {
+    query(criteria) {
+        return httputils.postJson('/admin/redis/query', criteria)
+    },
+    save(redisData) {
+        return httputils.postJson('/admin/redis/save', redisData)
+    },
+    delete(redisData) {
+        return httputils.postJson('/admin/redis/delete', redisData)
+    }
+}

+ 99 - 0
src/api/framework.js

@@ -0,0 +1,99 @@
+import store from '@/store'
+import demoMenus from '@/demo/demo-menus'
+import menus from '@/data/menus'
+import router from '@/router'
+
+const userInfo = { username: 'admin', permissions: ['demo'] }
+
+function toLogin() {
+    router.push('/login')
+}
+
+function checkMenu(menu, ps) {
+    let result = { name: menu.name, icon: menu.icon, path: menu.path }
+    if (menu.children) {
+        // 如果有下级菜单权限,则自动拥有上级菜单权限
+        result.children = []
+        menu.children.forEach(child => {
+            let submenu = checkMenu(child, ps)
+            if (submenu) {
+                result.children.push(submenu)
+            }
+        })
+        return result.children.length > 0 ? result : null
+    } else if (menu.opts) {
+        return menu.opts.some(opt => ps[opt.permission]) ? result : null
+    } else {
+        // 如果没有下级菜单且没有opts属性, 菜单可以直接访问,不需要权限
+        return result
+    }
+}
+
+export default {
+    /**
+     *  路由守卫, 每次路由跳转时验证登录
+     * @param {*} to
+     * @param {*} from
+     * @param {*} next
+     */
+    routerBeforeEach: async function(to, from, next) {
+        console.log('router before ', to)
+        if (to.path == '/auth' || to.path == '/login') {
+            next()
+        } else {
+            next()
+            // let userInfo = store.getters['layout/userInfo']
+            // if (!userInfo) {
+            //     // 本地是未登录状态, 保存目标页面地址, 去登录
+            //     let lastRoute = { path: to.path, params: to.params, query: to.query }
+            //     store.commit('setLastRoute', lastRoute)
+            //     toLogin()
+            // } else {
+            //     if (to.meta.breadcrumbs) {
+            //         store.dispatch('setBreadcrumb', to.meta.breadcrumbs)
+            //     }
+            //     next()
+            // }
+            return true
+        }
+    },
+
+    getMenus(permissions) {
+        let result = []
+        let allMenus = []
+        // 开发环境下展示demo页面
+        if (process.env.NODE_ENV === 'development') {
+            allMenus = demoMenus
+        }
+        allMenus = allMenus.concat(menus)
+        let ps = !permissions ? {} : permissions
+        allMenus.forEach(item => {
+            let menu = checkMenu(item, ps)
+            if (menu) {
+                result.push(menu)
+            }
+        })
+        return result
+    },
+
+    login(username, password) {
+        return new Promise((resolve, reject) => {
+            if (username == 'admin') {
+                resolve({ result: 'success', ssoToken: 'admin-token' })
+            } else {
+                resolve({ result: 'fail', message: 'username or password error' })
+            }
+        })
+    },
+
+    loadUserInfo() {
+        return new Promise((resolve, reject) => resolve({ result: 'success', ...userInfo }))
+    },
+
+    toLogout() {
+        // TODO
+        router.push('/login')
+    },
+
+    toLoginPage: toLogin
+}

+ 100 - 0
src/api/httputils.js

@@ -0,0 +1,100 @@
+import axios from 'axios'
+import store from '@/store'
+import { MessageBox } from 'element-ui'
+
+var CancelToken = axios.CancelToken
+var cancel
+
+// 创建axios实例
+const axiosservice = axios.create({
+    timeout: 30000, // 请求超时时间
+    retry: 4, //重新请求次数
+    retryDelay: 1000, //重新请求的间隔
+    credentials: true, // 接口每次请求会跨域携带cookie
+    cancelToken: new CancelToken(function executor(c) {
+        // executor 函数接收一个 cancel 函数作为参数
+        cancel = c
+    })
+})
+
+// axiosservice.interceptors.request.use(
+//     config => {
+//         config.withCredentials = true // 允许携带token ,这个是解决跨域产生的相关问题
+//         let token = store.getters['ssoToken']
+//         if (token) {
+//             config.headers = {
+//                 'sso-token': token
+//             }
+//         }
+//         return config
+//     },
+//     error => {
+//         return Promise.reject(error)
+//     }
+// )
+
+axiosservice.interceptors.response.use(
+    function(res) {
+        //在这里对返回的数据进行处理
+        let resp = res.data
+        if (resp.result === 'unauthc') {
+            store.commit('logined', false)
+            MessageBox.confirm('未登陆或登陆信息已失效, 是否重新登陆?', '提示', {
+                confirmButtonText: '确定',
+                cancelButtonText: '取消',
+                type: 'error'
+            })
+                .then(resp => {
+                    window.location.reload()
+                })
+                .catch(error => {
+                    console.log('')
+                })
+        }
+        return res
+    },
+    function(err) {
+        console.log('axios interceptors err = ', err)
+        return Promise.reject(err)
+    }
+)
+
+export default {
+    //获取cookie
+    getCookie(name) {
+        var arr,
+            reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)')
+        if ((arr = document.cookie.match(reg))) {
+            return unescape(arr[2])
+        } else {
+            /* 如果没有参数,那么就获取本域下的所有cookie */
+            return document.cookie
+        }
+    },
+
+    async getJson(url, params) {
+        try {
+            let response = await axiosservice({
+                url,
+                params,
+                method: 'get'
+            })
+            return response.data
+        } catch (err) {
+            throw err
+        }
+    },
+    async postJson(url, data) {
+        try {
+            let response = await axiosservice({
+                url,
+                data,
+                method: 'post'
+            })
+            return response.data
+        } catch (err) {
+            throw err
+        }
+    },
+    axios: axiosservice
+}

+ 21 - 0
src/api/system/role.js

@@ -0,0 +1,21 @@
+import httputils from '@/utils/httputils'
+export default {
+    query(criteria) {
+        return httputils.postJson('/admin/role/query', criteria)
+    },
+    create(role) {
+        return httputils.postJson('/admin/role/create', role)
+    },
+    update(role) {
+        return httputils.postJson('/admin/role/update', role)
+    },
+    delete(role) {
+        return httputils.postJson('/admin/role/delete', role)
+    },
+    getOperations(id) {
+        return httputils.getJson('/admin/role/getOperations?id=' + id)
+    },
+    setOperations(data) {
+        return httputils.postJson('/admin/role/setOperations', data)
+    }
+}

+ 15 - 0
src/api/system/user.js

@@ -0,0 +1,15 @@
+import httputils from '@/utils/httputils'
+export default {
+  query(criteria) {
+    return httputils.postJson('/admin/user/query', criteria)
+  },
+  create(user) {
+    return httputils.postJson('/admin/user/create', user)
+  },
+  update(user) {
+    return httputils.postJson('/admin/user/update', user)
+  },
+  delete(user) {
+    return httputils.postJson('/admin/user/delete', user)
+  }
+}

BIN
src/assets/logo-small.jpg


BIN
src/assets/logo.jpg


BIN
src/assets/logo.png


+ 38 - 0
src/components/HelloWorld.vue

@@ -0,0 +1,38 @@
+<template>
+    <div class='hello'>
+        <template v-for='i in 10'>
+            <h1 :key='i'>{{ msg }} ---- {{i}}</h1>
+            <h2 :key='i'>Essential Links</h2>
+        </template>
+    </div>
+</template>
+
+<script>
+export default {
+    name: 'HelloWorld',
+    data() {
+        return {
+            msg: 'Welcome to Your Vue.js App'
+        }
+    }
+}
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped>
+h1,
+h2 {
+    font-weight: normal;
+}
+ul {
+    list-style-type: none;
+    padding: 0;
+}
+li {
+    display: inline-block;
+    margin: 0 10px;
+}
+a {
+    color: #42b983;
+}
+</style>

+ 1 - 1
src/components/config_point/step3_edit/split_handle.vue

@@ -149,7 +149,7 @@ export default {
     .form {
     .form {
         .dev-know {
         .dev-know {
             margin-top: 5px;
             margin-top: 5px;
-            background: #e6e6e6;
+            background: #EBEEF5;
             padding: 5px 50px 5px 0;
             padding: 5px 50px 5px 0;
             width: 470px;
             width: 470px;
             position: relative;
             position: relative;

+ 154 - 174
src/data/menus.js

@@ -1,119 +1,100 @@
-export default {
-    demoMenus: [
-        {
-            icon: 'el-icon-fa-diamond',
-            name: 'Demo Page',
-            path: '/demo',
-            children: [
-                {
-                    icon: 'el-icon-fa-diamond',
-                    name: 'Form Panel',
-                    path: '/demo/form'
-                },
-                {
-                    icon: 'el-icon-fa-diamond',
-                    name: 'Table Panel',
-                    path: '/demo/table'
-                }
-            ]
-        }
-    ],
-    menus: [
-        {
-            path: '/system',
-            name: '系统管理',
-            icon: 'el-icon-fa-bank',
-            children: [
-                {
-                    path: '/system/users',
-                    name: '用户管理',
-                    icon: 'el-icon-fa-user',
-                    opts: [
-                        {
-                            name: '查看',
-                            basic: true,
-                            permission: 'system:user:query'
-                        }
-                    ]
-                }
-            ]
-        },
-        {
-            path: '/alarmconfig',
-            name: '报警设置',
-            icon: 'el-icon-fa-bank',
-            children: [
-                {
-                    path: '/alarmconfig/projsetting',
-                    name: '项目报警设置',
-                    icon: 'el-icon-fa-user',
-                    opts: [
-                        {
-                            name: '查看',
-                            basic: true,
-                            permission: 'system:role:query'
-                        }
-                    ]
-                },
-                {
-                    path: '/alarmconfig/projnotice',
-                    name: '项目报警通知设置',
-                    icon: 'el-icon-fa-user',
-                    opts: [
-                        {
-                            name: '查看',
-                            basic: true,
-                            permission: 'system:role:query'
-                        }
-                    ]
-                },
-                {
-                    path: '/alarmconfig/staffsetting',
-                    name: '为断数报警设定通知人员',
-                    icon: 'el-icon-fa-key',
-                    opts: [
-                        {
-                            name: '查看',
-                            basic: true,
-                            permission: 'system:role:query'
-                        }
-                    ]
-                }
-            ]
-        },
-        // 与fm相关的配置
-        {
-            path: '/fm',
-            name: '与FM相关设置',
-            icon: 'el-icon-fa-bank',
-            children: [
-                {
-                    path: '/fm/sopsetting',
-                    name: '通用问题与项目sop对应关系配置',
-                    icon: 'el-icon-fa-user',
-                    opts: [
-                        {
-                            name: '查看',
-                            basic: true,
-                            permission: 'system:role:query'
-                        }
-                    ]
-                },
-                {
-                    path: '/fm/rulesetting',
-                    name: '项目计划抢单规则设定',
-                    icon: 'el-icon-fa-user',
-                    opts: [
-                        {
-                            name: '查看',
-                            basic: true,
-                            permission: 'system:role:query'
-                        }
-                    ]
-                }
-            ]
-        },
+export default [
+    {
+        path: '/system',
+        name: '系统管理',
+        icon: 'el-icon-fa-bank',
+        children: [
+            {
+                path: '/system/users',
+                name: '用户管理',
+                icon: 'el-icon-fa-user',
+                opts: [
+                    {
+                        name: '查看',
+                        basic: true,
+                        permission: 'system:user:query'
+                    }
+                ]
+            }
+        ]
+    },
+        //报警设置
+        // {
+        //     path: '/alarmconfig',
+        //     name: '报警设置',
+        //     icon: 'el-icon-fa-bank',
+        //     children: [
+        //         {
+        //             path: '/alarmconfig/projsetting',
+        //             name: '项目报警设置',
+        //             icon: 'el-icon-fa-user',
+        //             opts: [
+        //                 {
+        //                     name: '查看',
+        //                     basic: true,
+        //                     permission: 'system:role:query'
+        //                 }
+        //             ]
+        //         },
+        //         {
+        //             path: '/alarmconfig/projnotice',
+        //             name: '项目报警通知设置',
+        //             icon: 'el-icon-fa-user',
+        //             opts: [
+        //                 {
+        //                     name: '查看',
+        //                     basic: true,
+        //                     permission: 'system:role:query'
+        //                 }
+        //             ]
+        //         },
+        //         {
+        //             path: '/alarmconfig/staffsetting',
+        //             name: '为断数报警设定通知人员',
+        //             icon: 'el-icon-fa-key',
+        //             opts: [
+        //                 {
+        //                     name: '查看',
+        //                     basic: true,
+        //                     permission: 'system:role:query'
+        //                 }
+        //             ]
+        //         }
+        //     ]
+        // },
         // 与fm相关的配置
         // 与fm相关的配置
+        // {
+        //     path: '/fm',
+        //     name: '与FM相关设置',
+        //     icon: 'el-icon-fa-bank',
+        //     children: [
+        //         {
+        //             path: '/fm/sopsetting',
+        //             name: '通用问题与项目sop对应关系配置',
+        //             icon: 'el-icon-fa-user',
+        //             opts: [
+        //                 {
+        //                     name: '查看',
+        //                     basic: true,
+        //                     permission: 'system:role:query'
+        //                 }
+        //             ]
+        //         },
+        //         {
+        //             path: '/fm/rulesetting',
+        //             name: '项目计划抢单规则设定',
+        //             icon: 'el-icon-fa-user',
+        //             opts: [
+        //                 {
+        //                     name: '查看',
+        //                     basic: true,
+        //                     permission: 'system:role:query'
+        //                 }
+        //             ]
+        //         }
+        //     ]
+        // },
+        // 点位配置
         {
         {
             path: '/point',
             path: '/point',
             name: '点位表管理',
             name: '点位表管理',
@@ -338,64 +319,63 @@ export default {
             ]
             ]
         },
         },
         //环境调节
         //环境调节
-        {
-            path: '/environment',
-            name: '环境调节',
-            icon: 'el-icon-fa-bank',
-            children: [
-                {
-                    path: '/environment/envlist',
-                    name: '环境服务定制设置',
-                    icon: 'el-icon-fa-user',
-                    opts: [
-                        {
-                            name: '查看',
-                            basic: true,
-                            permission: 'system:role:query'
-                        }
-                    ]
-                }
-            ]
-        },
+        // {
+        //     path: '/environment',
+        //     name: '环境调节',
+        //     icon: 'el-icon-fa-bank',
+        //     children: [
+        //         {
+        //             path: '/environment/envlist',
+        //             name: '环境服务定制设置',
+        //             icon: 'el-icon-fa-user',
+        //             opts: [
+        //                 {
+        //                     name: '查看',
+        //                     basic: true,
+        //                     permission: 'system:role:query'
+        //                 }
+        //             ]
+        //         }
+        //     ]
+        // },
         //市场及商务
         //市场及商务
-        {
-            path: '/market',
-            name: '市场及商务',
-            icon: 'el-icon-fa-bank',
-            children: [
-                {
-                    path: '/market/own',
-                    name: '业主管理',
-                    icon: 'el-icon-fa-user',
-                    opts: [
-                        {
-                            name: '查看',
-                            basic: true,
-                            permission: 'system:role:query'
-                        }
-                    ]
-                }
-            ]
-        },
+        // {
+        //     path: '/market',
+        //     name: '市场及商务',
+        //     icon: 'el-icon-fa-bank',
+        //     children: [
+        //         {
+        //             path: '/market/own',
+        //             name: '业主管理',
+        //             icon: 'el-icon-fa-user',
+        //             opts: [
+        //                 {
+        //                     name: '查看',
+        //                     basic: true,
+        //                     permission: 'system:role:query'
+        //                 }
+        //             ]
+        //         }
+        //     ]
+        // },
         //revit服务器端化的web功能
         //revit服务器端化的web功能
-        {
-            path: '/revitservice',
-            name: 'revit服务器端化',
-            icon: 'el-icon-fa-bank',
-            children: [
-                {
-                    path: '/revitservice/revit',
-                    name: '设计中',
-                    icon: 'el-icon-fa-user',
-                    opts: [
-                        {
-                            name: '查看',
-                            basic: true,
-                            permission: 'system:role:query'
-                        }
-                    ]
-                }
-            ]
-        },
-    ]
-}
+        // {
+        //     path: '/revitservice',
+        //     name: 'revit服务器端化',
+        //     icon: 'el-icon-fa-bank',
+        //     children: [
+        //         {
+        //             path: '/revitservice/revit',
+        //             name: '设计中',
+        //             icon: 'el-icon-fa-user',
+        //             opts: [
+        //                 {
+        //                     name: '查看',
+        //                     basic: true,
+        //                     permission: 'system:role:query'
+        //                 }
+        //             ]
+        //         }
+        //     ]
+        // },
+]

+ 32 - 0
src/demo/demo-menus.js

@@ -0,0 +1,32 @@
+export default [
+    {
+        icon: 'el-icon-fa-diamond',
+        name: 'Demo Page',
+        path: '/demo',
+        children: [
+            {
+                icon: 'el-icon-fa-diamond',
+                name: 'Form Panel',
+                path: '/demo/form'
+            },
+            {
+                icon: 'el-icon-fa-diamond',
+                name: 'Table Panel',
+                path: '/demo/table'
+            }, {
+                icon: 'el-icon-fa-diamond',
+                name: '点位配置',
+                path: '/demo/point'
+            },
+            {
+                icon: 'el-icon-fa-diamond',
+                name: '数据整理',
+                path: '/demo/data'
+            }, {
+                icon: 'el-icon-fa-diamond',
+                name: '报警配置',
+                path: '/demo/alarm'
+            }
+        ]
+    }
+]

+ 53 - 0
src/demo/demo-routes.js

@@ -0,0 +1,53 @@
+import LayoutMain from '@/framework/layout/Main'
+
+import HelloWorld from '@/components/HelloWorld'
+import TablePageDemo from '@/demo/views/table/TablePageDemo'
+import FormPageDemo from '@/demo/views/form/FormPageDemo'
+
+import Ponit from './test/fugy/index'
+import Data from './test/wangsw/index'
+import Alarm from './test/zhulz/index'
+
+export default [
+    {
+        path: '/demo',
+        name: 'LayoutMain',
+        component: LayoutMain,
+        children: [
+            {
+                path: '',
+                name: 'HelloWorld',
+                component: HelloWorld,
+                meta: { keepAlive: true, breadcrumbs: [] }
+            },
+            {
+                path: 'table',
+                name: 'TablePageDemo',
+                component: TablePageDemo,
+                meta: { keepAlive: true, breadcrumbs: [{ label: 'Demo' }, { label: 'Table' }] }
+            },
+            {
+                path: 'form',
+                name: 'FormPageDemo',
+                component: FormPageDemo,
+                meta: { keepAlive: true, breadcrumbs: [{ label: 'Demo' }, { label: 'Form' }] }
+            },
+            {
+                path: 'point',
+                name: 'point',
+                component: Ponit,
+                meta: { keepAlive: true, breadcrumbs: [{ label: 'Demo' }, { label: 'Form' }] }
+            }, {
+                path: 'data',
+                name: 'data',
+                component: Data,
+                meta: { keepAlive: true, breadcrumbs: [{ label: 'Demo' }, { label: 'Form' }] }
+            }, {
+                path: 'alarm',
+                name: 'alarm',
+                component: Alarm,
+                meta: { keepAlive: true, breadcrumbs: [{ label: 'Demo' }, { label: 'Form' }] }
+            }
+        ]
+    }
+]

+ 131 - 0
src/demo/test/fugy/Dialog.vue

@@ -0,0 +1,131 @@
+<template>
+    <el-dialog title='根据识别关键内容批量对象数据字典' :visible.sync='dialogVisible' width='900px'>
+        <div class='box'>
+            <div class='cond'>
+                <span class='label'>设备参数</span>
+                <el-cascader :options='options1' v-model='selectedOptions' @change='handleChange' clearable></el-cascader>
+            </div>
+            <div class='content'>
+                <el-tabs style v-model='activeName'>
+                    <el-tab-pane label='1、确定与数据字典中信息点的对应' name='0'>
+                        <tab1></tab1>
+                    </el-tab-pane>
+                    <el-tab-pane label='2、确定值的处理方式' name='1'>
+                        <tab2></tab2>
+                    </el-tab-pane>
+                    <el-tab-pane label='3、缺认并维护涉及到的原始点位对应的设备标识' name='2'>
+                        <tab3></tab3>
+                    </el-tab-pane>
+                </el-tabs>
+            </div>
+        </div>
+
+        <span slot='footer' class='dialog-footer'>
+            <el-button type='primary' @click="pre" v-if="activeName > 0">上一步</el-button>
+            <el-button type='primary' @click="next" v-if="activeName < 2">下一步</el-button>
+            <el-button type='primary' @click='dialogVisible = false' v-if="activeName == 2">保 存</el-button>
+        </span>
+    </el-dialog>
+</template>
+
+<script>
+//components
+import Tab1 from './Tab1'
+import Tab2 from './Tab2'
+import Tab3 from './Tab3'
+import noHandle from '@/components/config_point/step3_edit/no_handle'
+import autoHandle from '@/components/config_point/step3_edit/auto_handle'
+import enumHandle from '@/components/config_point/step3_edit/enum_handle'
+import formulaHandle from '@/components/config_point/step3_edit/formula_handle'
+import splitHandle from '@/components/config_point/step3_edit/split_handle'
+export default {
+    name: '',
+    data() {
+        return {
+            dialogVisible: false,
+            selectedOptions: [],
+            activeName: '0',
+            tabNameArr: ["0", "1", '2'],
+            options1: [
+                {
+                    value: '100',
+                    label: '3#',
+                    children: [
+                        {
+                            value: '101',
+                            label: '水阀'
+                        }
+                    ]
+                },
+                {
+                    value: '200',
+                    label: '2#',
+                    children: [
+                        {
+                            value: '201',
+                            label: '温度'
+                        },
+                        {
+                            value: '201',
+                            label: '开关状态'
+                        }
+                    ]
+                },
+                {
+                    value: '300',
+                    label: '水阀',
+                    children: [
+                        {
+                            value: '301',
+                            label: '温度'
+                        }
+                    ]
+                }
+            ],
+            
+            
+        }
+    },
+    components: {
+        Tab1,
+        Tab2,
+        Tab3,
+    },
+    methods: {
+        
+        show() {
+            this.dialogVisible = true
+        },
+        handleChange() {},
+        next() {
+            this.activeName = this.tabNameArr[this.activeName * 1 + 1]
+        },
+        pre() {
+            this.activeName = this.tabNameArr[this.activeName * 1 - 1]
+        }
+    }
+}
+</script>
+
+<style scoped lang='less'>
+@labelColor: #606266;
+.box {
+    height: 500px;
+    overflow: auto;
+    .cond {
+        text-align: right;
+        .label {
+            color: @labelColor;
+        }
+    }
+    .content {
+        .form {
+            width: 520px;
+            margin: 0 auto;
+        }
+        .form-step2 {
+            height: 400px;
+        }
+    }
+}
+</style>

+ 167 - 0
src/demo/test/fugy/Step3.vue

@@ -0,0 +1,167 @@
+<template>
+    <div class='box1' style='display: flex;flex-direction: column;flex-grow: 1;flex-shrink: 1;'>
+        <el-switch v-model='ch' size='small'></el-switch>
+        <table-page-template>
+            <div class='con-box' slot='form'>
+                <el-button type='primary'>根据关键内容批量标准化设备标识</el-button>
+                <el-button type='primary' @click='someDictHandle'>根据关键内容批量对应数据字典</el-button>
+                <el-checkbox class='checkbox' v-model='checked'>只显示未标准化的原始点位</el-checkbox>
+            </div>
+            <!-- <div class='table-box' > -->
+                <el-table :data='tableData' style='width: 100%' border slot='table' class='data-table'>
+                    <el-table-column header-align='center' align='center' prop='a' label='原始点位描述' width='180'></el-table-column>
+                    <el-table-column sortable header-align='center' align='center' prop='b' label='位置标签' width='180'>
+                        <template slot-scope='scope'>
+                            <el-tag style='margin-left: 5px;' v-for='(item,index) in scope.row.b' :key='index' size='mini'>{{item}}</el-tag>
+                        </template>
+                    </el-table-column>
+                    <el-table-column header-align='center' align='center' prop='c' label='设备类型'></el-table-column>、
+                    <el-table-column header-align='center' align='center' prop='d' label='设备参数'></el-table-column>
+                    <el-table-column header-align='center' align='center' prop='f' label='设备标识'></el-table-column>
+                    <el-table-column header-align='center' align='center' prop='g' label='数据字典设备类'></el-table-column>
+                    <el-table-column header-align='center' align='center' prop='h' label='值处理方式'></el-table-column>
+                    <el-table-column header-align='center' align='center' prop='i' label='备注'></el-table-column>
+                    <el-table-column header-align='center' align='center' label='操作' width='80' class-name='ttt'>
+                        <template>
+                            <el-button type='primary' size='mini'>编辑</el-button>
+                        </template>
+                    </el-table-column>
+                </el-table>
+            <!-- </div> -->
+            <base-pagination :total='456' @pageChanged='pageChanged' slot='pagination'></base-pagination>
+            
+        </table-page-template>
+        <sg-dialog ref='some-dialog'></sg-dialog>
+        <!-- component -->
+        
+     </div>
+</template>
+<script>
+import './index.less'
+import SgDialog from './Dialog'
+export default {
+    name: 'point',
+    data() {
+        return {
+            ch: true,
+            checked: false,
+            currentPage4: 1,
+            tableData: [
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs',
+                    f: '1、2',
+                    g: '变压器-运行状态',
+                    h: '无需处理',
+                    i: '--'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs',
+                    f: '1、2',
+                    g: '变压器-运行状态',
+                    h: '无需处理',
+                    i: '--'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs',
+                    f: '1、2',
+                    g: '变压器-运行状态',
+                    h: '无需处理',
+                    i: '--'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs',
+                    f: '1、2',
+                    g: '变压器-运行状态',
+                    h: '无需处理',
+                    i: '--'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs',
+                    f: '1、2',
+                    g: '变压器-运行状态',
+                    h: '无需处理',
+                    i: '--'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs',
+                    f: '1、2',
+                    g: '变压器-运行状态',
+                    h: '无需处理',
+                    i: '--'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs',
+                    f: '1、2',
+                    g: '变压器-运行状态',
+                    h: '无需处理',
+                    i: '--'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs',
+                    f: '1、2',
+                    g: '变压器-运行状态',
+                    h: '无需处理',
+                    i: '--'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs',
+                    f: '1、2',
+                    g: '变压器-运行状态',
+                    h: '无需处理',
+                    i: '--'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs',
+                    f: '1、2',
+                    g: '变压器-运行状态',
+                    h: '无需处理',
+                    i: '--'
+                }
+            ]
+        }
+    },
+    components: {
+        SgDialog
+    },
+    methods: {
+        handleSizeChange() {},
+        handleCurrentChange() {},
+        someDictHandle() {
+            this.$refs['some-dialog'].show()
+        },
+        pageChanged(){}
+    }
+}
+</script>
+<style lang="less">
+</style>

+ 164 - 0
src/demo/test/fugy/Step4.vue

@@ -0,0 +1,164 @@
+<template>
+    <!-- <div class='box1'> -->
+        <table-page-template>
+            <div class='con-box' slot='form'>
+                <el-button type='primary'>根据关键内容批量标准化设备标识</el-button>
+                <el-button type='primary' @click='someDictHandle'>根据关键内容批量对应数据字典</el-button>
+                <el-checkbox class='checkbox' v-model='checked'>只显示未标准化的原始点位</el-checkbox>
+            </div>
+            <!-- <div class='table-box' > -->
+                <el-table :data='tableData' style='width: 100%' border slot='table'>
+                    <el-table-column header-align='center' align='center' prop='a' label='原始点位描述' width='180'></el-table-column>
+                    <el-table-column sortable header-align='center' align='center' prop='b' label='位置标签' width='180'>
+                        <template slot-scope='scope'>
+                            <el-tag style='margin-left: 5px;' v-for='(item,index) in scope.row.b' :key='index' size='mini'>{{item}}</el-tag>
+                        </template>
+                    </el-table-column>
+                    <el-table-column header-align='center' align='center' prop='c' label='设备类型'></el-table-column>、
+                    <el-table-column header-align='center' align='center' prop='d' label='设备参数'></el-table-column>
+                    <el-table-column header-align='center' align='center' prop='f' label='设备标识'></el-table-column>
+                    <el-table-column header-align='center' align='center' prop='g' label='数据字典设备类'></el-table-column>
+                    <el-table-column header-align='center' align='center' prop='h' label='值处理方式'></el-table-column>
+                    <el-table-column header-align='center' align='center' prop='i' label='备注'></el-table-column>
+                    <el-table-column header-align='center' align='center' label='操作' width='80'>
+                        <template>
+                            <el-button type='text' size='mini'>编辑</el-button>
+                        </template>
+                    </el-table-column>
+                </el-table>
+            <!-- </div> -->
+            <base-pagination :total='456' @pageChanged='pageChanged' slot='pagination'></base-pagination>
+            <sg-dialog ref='some-dialog'></sg-dialog>
+        </table-page-template>
+        <!-- component -->
+        
+    <!-- </div> -->
+</template>
+<script>
+import './index.less'
+import SgDialog from './Dialog'
+export default {
+    name: 'point',
+    data() {
+        return {
+            checked: false,
+            currentPage4: 1,
+            tableData: [
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs',
+                    f: '1、2',
+                    g: '变压器-运行状态',
+                    h: '无需处理',
+                    i: '--'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs',
+                    f: '1、2',
+                    g: '变压器-运行状态',
+                    h: '无需处理',
+                    i: '--'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs',
+                    f: '1、2',
+                    g: '变压器-运行状态',
+                    h: '无需处理',
+                    i: '--'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs',
+                    f: '1、2',
+                    g: '变压器-运行状态',
+                    h: '无需处理',
+                    i: '--'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs',
+                    f: '1、2',
+                    g: '变压器-运行状态',
+                    h: '无需处理',
+                    i: '--'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs',
+                    f: '1、2',
+                    g: '变压器-运行状态',
+                    h: '无需处理',
+                    i: '--'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs',
+                    f: '1、2',
+                    g: '变压器-运行状态',
+                    h: '无需处理',
+                    i: '--'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs',
+                    f: '1、2',
+                    g: '变压器-运行状态',
+                    h: '无需处理',
+                    i: '--'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs',
+                    f: '1、2',
+                    g: '变压器-运行状态',
+                    h: '无需处理',
+                    i: '--'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs',
+                    f: '1、2',
+                    g: '变压器-运行状态',
+                    h: '无需处理',
+                    i: '--'
+                }
+            ]
+        }
+    },
+    components: {
+        SgDialog
+    },
+    methods: {
+        handleSizeChange() {},
+        handleCurrentChange() {},
+        someDictHandle() {
+            this.$refs['some-dialog'].show()
+        },
+        pageChanged(){}
+    }
+}
+</script>
+<style lang="less">
+</style>

File diff suppressed because it is too large
+ 1730 - 0
src/demo/test/fugy/Tab1.vue


+ 68 - 0
src/demo/test/fugy/Tab2.vue

@@ -0,0 +1,68 @@
+<template>
+    <el-form class='form' :rules='rules' ref='form' :model='form' label-width='140px'>
+        <el-form-item label='值处理方式' prop='DataRuleType'>
+            <el-select v-model='form.DataRuleType' placeholder='请选择'>
+                <el-option v-for='item in handleTypeArr' :key='item.value' :label='item.label' :value='item.value'></el-option>
+            </el-select>
+        </el-form-item>
+        <!-- components -->
+        <no-handle ref='noHandle' v-if='form.DataRuleType == "无需处理,直接使用"'></no-handle>
+        <auto-handle ref='autoHandle' v-else-if='form.DataRuleType == "需自动单位转换"' :unitObj='{}'></auto-handle>
+        <enum-handle ref='enumHandle' v-else-if='form.DataRuleType == "需按设置枚举转换"'></enum-handle>
+        <formula-handle ref='formulaHandle' v-else-if='form.DataRuleType == "需按公式转换"'></formula-handle>
+        <split-handle ref='splitHandle' v-else-if='form.DataRuleType == "需拆分处理"'></split-handle>
+    </el-form>
+</template>
+
+<script>
+import noHandle from '@/components/config_point/step3_edit/no_handle'
+import autoHandle from '@/components/config_point/step3_edit/auto_handle'
+import enumHandle from '@/components/config_point/step3_edit/enum_handle'
+import formulaHandle from '@/components/config_point/step3_edit/formula_handle'
+import splitHandle from '@/components/config_point/step3_edit/split_handle'
+export default {
+    data() {
+        return {
+            form: {
+                dict: [],
+                DataRuleType: ''
+            },
+            handleTypeArr: [
+                {
+                    label: '无需处理,直接使用',
+                    value: '无需处理,直接使用'
+                },
+                {
+                    label: '需自动单位转换',
+                    value: '需自动单位转换'
+                },
+                {
+                    label: '需按设置枚举转换',
+                    value: '需按设置枚举转换'
+                },
+                {
+                    label: '需按公式转换',
+                    value: '需按公式转换'
+                },
+                {
+                    label: '需拆分处理',
+                    value: '需拆分处理'
+                }
+            ],
+            rules: {
+                DataRuleType: [{ required: true, message: '请选择值处理方式', trigger: 'change' }]
+            }
+        }
+    },
+    components: {
+        noHandle,
+        autoHandle,
+        enumHandle,
+        formulaHandle,
+        splitHandle
+    }
+}
+</script>
+
+<style>
+</style>

+ 87 - 0
src/demo/test/fugy/Tab3.vue

@@ -0,0 +1,87 @@
+<template>
+    <el-table :data='tableData' style='width: 100%' border size='medium' height='400'>
+        <el-table-column header-align='center' align='center' label='设备标识' width='180'>
+            <template slot-scope='scope'>
+                <el-tag style='margin-left: 5px;' v-for='(item ,index) in scope.row.b' :key='index'>{{item}}</el-tag>
+                <el-tag style='margin-left: 5px;' type='warning'>324#</el-tag>
+            </template>
+        </el-table-column>
+        <el-table-column sortable header-align='center' align='center' label='原始点位描述' width='180' prop='a'></el-table-column>
+        <el-table-column header-align='center' align='center' prop='c' label='位置标签'></el-table-column>、
+        <el-table-column header-align='center' align='center' prop='d' label='备注'></el-table-column>
+    </el-table>
+</template>
+
+<script>
+export default {
+    data() {
+        return {
+            tableData: [
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs'
+                },
+                {
+                    a: '1-14遥控测试',
+                    b: ['电梯厅', '1F'],
+                    c: '电器',
+                    d: '12313#fs'
+                }
+            ]
+        }
+    }
+}
+</script>
+
+<style>
+</style>

+ 20 - 0
src/demo/test/fugy/index.less

@@ -0,0 +1,20 @@
+@marginTop: 20px;
+.box {    
+    .step-box {
+
+    }
+    .con-box{
+        // margin-top: @marginTop;
+        text-align: center;
+        .checkbox {
+            float: right;
+        }
+    }
+    .table-box {
+        margin-top: @marginTop;
+    }
+    .page-box {
+        margin-top: @marginTop;
+        text-align: center;
+    }
+}

+ 35 - 0
src/demo/test/fugy/index.vue

@@ -0,0 +1,35 @@
+<template>
+    <div class='box'>
+        <el-tabs v-model='activeName' @tab-click='handleClick'>
+            <el-tab-pane label='原始点位表收集' name='first'>用户管理</el-tab-pane>
+            <el-tab-pane label='原始点位描述关键内容识别' name='second'>配置管理</el-tab-pane>
+            <el-tab-pane label='原始点位描述标准化' name='third'>
+                <sg-step></sg-step>
+            </el-tab-pane>
+            <el-tab-pane label='点位表处理结果检查' name='fourth'>定时任务补偿</el-tab-pane>
+        </el-tabs>
+    </div>
+</template>
+<script>
+import SgStep from './Step3'
+
+export default {
+    name: 'point',
+    data() {
+        return {
+            activeName: 'third'
+        }
+    },
+    components: {
+        SgStep
+    },
+    methods: {
+        handleClick() {}
+    }
+}
+</script>
+<style lang="less" scoped>
+.box {
+    padding: 20px;
+}
+</style>

+ 15 - 0
src/demo/test/wangsw/index.vue

@@ -0,0 +1,15 @@
+<template>
+   <div>
+        2
+    </div>
+</template>
+
+<script>
+export default {
+
+}
+</script>
+
+<style>
+
+</style>

+ 100 - 0
src/demo/test/zhulz/alarmCode.vue

@@ -0,0 +1,100 @@
+<template>
+  <div class="alarm-code">
+    <div class="alarm-item-box">
+        <div class="radio-box">
+            <el-radio-group v-model="radioValue" @change="radioChange">
+                <el-radio-button label="fixed">固定条目</el-radio-button>
+                <el-radio-button label="customed">自定义条目</el-radio-button>                
+            </el-radio-group>
+        </div>
+        <div class="table-box">
+            <el-table
+            ref="multipleTable"
+            :loading="loading"
+            :data="data"
+            tooltip-effect="dark"
+            style="width: 100%"
+            border
+            @selection-change="handleSelectionChange">                
+                <el-table-column
+                prop="code"
+                align="center"
+                label="报警条目编码"
+                width="130">                
+                </el-table-column>
+                <el-table-column
+                header-align="center"
+                prop="name"
+                label="报警条目名称">
+                </el-table-column>
+                <el-table-column
+                type="selection"
+                >
+                </el-table-column>
+            </el-table>
+        </div>
+    </div>   
+  </div>
+</template>
+
+<script>
+export default {
+  components: {
+
+  },
+
+  mixins: [],
+
+  props: {
+
+  },
+
+  data () {
+    return {
+      data:[
+        {name:'集水坑超高液位报警',code:2003},
+        {name:'集水坑超低液位污水泵未停止报警',code:2004},
+        {name:'冷冻水泵电源电压过高',code:1024},
+        {name:'新风机组测试报警',code:100001},
+        {name:'潜污泵断电报警',code:2001},
+        {name:'集水坑超高液位潜污泵未启动报警',code:2002},
+      ],
+       radioValue: 'fixed', //默认固定
+    }
+  },
+
+  computed: {
+
+  },
+
+  mounted() {
+
+  },
+
+  methods: {
+     // radio改变事件
+        radioChange(val) {
+            this.multipleSelection = [];
+            this.alarmItemArr = [];
+            this.getAlarmItem();
+        },
+         handleSelectionChange(val,index) {
+            this.multipleSelection = val;
+        },
+  },
+
+}
+</script>
+
+<style scoped lang="less" >
+.alarm-code{
+  .radio-box{
+      text-align: center;
+  }
+  .table-box{
+      height: 500px;
+      overflow-y: auto;
+      margin-top: 10px;
+  }
+}
+</style>

+ 426 - 0
src/demo/test/zhulz/index.vue

@@ -0,0 +1,426 @@
+<template>
+    <div class="alarm-notes">
+        <table-page-template>
+        <div class="select-list" slot='form'>
+            <el-select v-model="project" class="item" size="small" placeholder="请选择项目">
+                <el-option
+                v-for="item in projects"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value">
+                </el-option>
+            </el-select>
+             <el-cascader
+                class="item"
+                size="small"
+                clearable
+                placeholder="请选择对象位置"
+                :options="positions"
+                v-model="position"
+                @change="handleChange">
+            </el-cascader>
+            <el-select v-model="level" class="item" clearable size="small" placeholder="请选择严重程度">
+                <el-option
+                v-for="item in levels"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value">
+                </el-option>
+            </el-select>
+            <el-select v-model="staff" class="item" clearable size="small" placeholder="请选择人员">
+                <el-option
+                v-for="item in staffs"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value">
+                </el-option>
+            </el-select>
+            <el-select v-model="type" class="item" clearable size="small" placeholder="请选择报警分类">
+                <el-option
+                v-for="item in types"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value">
+                </el-option>
+            </el-select>
+            <div class="btn-al">
+                 <el-button type="primary" size="small" style="width:200px" @click="alarmDialogVisible = true">报警条目</el-button>
+            </div>
+        </div>
+        <div class="sg-table" slot="table">
+            <el-radio-group v-model="notes" size="small" class="item">
+                <el-radio-button label="alarm">通过报警查看通知人员</el-radio-button>
+                <el-radio-button label="staff">通过人员查看报警通知</el-radio-button>
+            </el-radio-group>
+            <el-checkbox v-model="checked" class="check-note">只看尚未设定人员通知的报警</el-checkbox>
+            <el-button type="primary" size="small" class="btn-alarm" @click='setUser'>为所选报警统一设定通知人员</el-button>
+           <el-table
+                ref="multipleTable"
+                :data="tableData"
+                border
+                tooltip-effect="dark"
+                style="width: 100%"
+                @selection-change="handleSelectionChange">
+                <el-table-column
+                type="selection"
+                align="center"
+                width="55">
+                </el-table-column>
+                <el-table-column
+                align="center"
+                prop="classify"
+                label="报警分类"
+                width="130">
+                </el-table-column>
+                <el-table-column
+                prop="name"
+                header-align="center"
+                label="适用对象实例"
+                >
+                </el-table-column>
+                <el-table-column
+                prop="alarm"
+                header-align="center"
+                label="报警条目名称"
+                >
+                </el-table-column>
+                <el-table-column
+                prop="code"
+                label="报警条目编码"
+                align="center"
+                width="130"
+                >
+                </el-table-column>
+                <el-table-column
+                prop="level"
+                label="严重程度"
+                align="center"
+                width="80"
+               >
+                </el-table-column>
+                <el-table-column label="通知人员" width="80" align="center">
+                    <el-button
+                    size="small"
+                    type="text"
+                    @click="dialogVisible = true">设定
+                    </el-button>
+                </el-table-column>
+            </el-table>
+        </div>
+        <base-pagination :total='456' @pageChanged='pageChanged' slot='pagination'></base-pagination>
+        </table-page-template>
+        <el-dialog
+            title="设定通知人员"
+            :visible.sync="dialogVisible"
+            width="900px" height="500px"
+            >
+             <div class="box" v-if="userData.length">
+            <ul class="ul-box">
+                <li class="tit">
+                <p>人员姓名及通知方式</p>
+                </li>
+                <li v-for="(item, index) in userData" :key="index">
+                    <p>
+                        <span class="name">{{item.name}}</span>
+                        <span class="name">{{item.phone}}</span>
+                        <span class="name">{{item.email}}</span>
+                    </p>         
+                <span>
+                    <v-check-box :sendMessage='item.sendMessage' :sendEmail='item.sendEmail' :sendWechat='item.sendWechat' :define="index" @change="checkBoxChange"></v-check-box>
+                </span>
+                </li>
+            </ul>      
+            </div>
+            <div v-else style="text-align:center;min-height:100px;">暂无人员</div>
+            <p>
+                <el-button type="primary" style="margin-top:10px" icon="el-icon-setting" @click="manageUser">管理通知人员</el-button>
+            </p>
+            <span slot="footer" class="dialog-footer">
+                <el-button @click="dialogVisible = false">取 消</el-button>
+                <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
+            </span>
+        </el-dialog>
+        <el-dialog
+            title="管理通知人员"
+            :visible.sync="manageDialogVisible"
+            width="900px" height="500px"
+            >
+           <manage-note></manage-note>
+        </el-dialog>
+        <el-dialog
+            title="选择报警条目"
+            :visible.sync="alarmDialogVisible"
+            width="900px" height="500px"
+            >
+          <alarm-code></alarm-code>
+           <span slot="footer" class="dialog-footer">
+                <el-button @click="alarmDialogVisible = false">取 消</el-button>
+                <el-button type="primary" @click="alarmDialogVisible = false">确 定</el-button>
+            </span>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+import manageNote from './manageNote'
+import alarmCode from './alarmCode'
+export default {
+    data(){
+        return {
+            alarmDialogVisible:false,
+            dialogVisible: false,
+            manageDialogVisible:false,
+            projects: [{
+                value: 'Pj4419000006',
+                label: '厚街万科城市广场'
+                }, {
+                value: 'Pj4419000003',
+                label: '长安万科广场'
+                }, {
+                value: 'Pj4419000008',
+                label: '松湖万科生活广场'
+                }, {
+                value: 'Pj1101020002',
+                label: '北京中海地产大厦'
+                }, {
+                value: 'Pj1101080002',
+                label: '新华创新大厦'
+                },{
+                value: 'Pj4201050001',
+                label: '武汉亚心总医院'
+                }, {
+                value: 'Pj1101010001',
+                label: '北京中海地产广场'
+                }],
+            project: 'Pj1101080002',
+            positions: [{
+                value: '6',
+                label: '6号楼',
+                children: [{
+                    value: 'f01',
+                    label: '地下一层',
+                    children: [{
+                        value: 'B1F1',
+                        label: 'B1F-5#变压器房'
+                        }, {
+                        value: 'B1F2',
+                        label: 'B1F-1#变压器房'
+                        }, {
+                        value: 'B1F3',
+                        label: 'B1F-2#变压器房'
+                        }, {
+                        value: 'B1F4',
+                        label: 'B1F-2#门内公区'
+                    }],
+                },{
+                    value: 'f02',
+                    label: '地下二层',
+                    children: [{
+                        value: 'B2F1',
+                        label: 'B2F-5#变压器房'
+                        }, {
+                        value: 'B2F2',
+                        label: 'B2F-1#变压器房'
+                        }, {
+                        value: 'B2F3',
+                        label: 'B2F-2#变压器房'
+                        }, {
+                        value: 'B2F4',
+                        label: 'B2F-2#门内公区'
+                    }]
+                },{
+                   value: 'f11',
+                   label: '地上一层',
+                   children: [{
+                        value: '1F1',
+                        label: '1F-公区'
+                        }, {
+                        value: '1F2',
+                        label: '1F-门内公区'
+                        }, {
+                        value: '1F3',
+                        label: '1F-1#门内公区'
+                        }, {
+                        value: '1F4',
+                        label: '1F-6#门内公区'
+                    }],  
+                },{
+                   value: 'f12',
+                   label: '地上二层', 
+                },{
+                    value:'f13',
+                    label: '地上三层',
+                },{
+                    value:'f14',
+                    label: '地上四层',
+                }]
+            }],
+            position:[],
+            levels: [{
+                value: '0',
+                label: 'S'
+                }, {
+                value: '1',
+                label: 'A'
+                }, {
+                value: '2',
+                label: 'B'
+                }, {
+                value: '3',
+                label: 'C'
+                }, {
+                value: '4',
+                label: 'D'
+                }],
+            level: '',
+            staffs: [{
+                value: '0',
+                label: '人员全部'
+                }],
+            staff: '',
+            types: [{
+                value: '0',
+                label: '环境报警'
+                }, {
+                value: '1',
+                label: '安全报警'
+                }],
+            type: '', 
+            notes: "alarm",
+            checked: false,
+            tableData: [{
+                classify: '--',
+                name: '1#冷冻水泵 - HJWK-6号楼-B2-KT-ZYZL-LDSB-001',
+                alarm: '冷冻水泵电源电压过高',
+                code:'1024',
+                level:'A'
+                }, {
+                classify: '环境报警',
+                name: '2#冷冻水泵 - HJWK-6号楼-B2-KT-ZYZL-LDSB-002',
+                alarm: '冷冻水泵电源电压过高',
+                code:'1024',
+                level:'A'
+                }, {
+                classify: '环境报警',
+                name: '3#冷冻水泵 - HJWK-6号楼-B2-KT-ZYZL-LDSB-003',
+                alarm: '冷冻水泵电源电压过高',
+                code:'1024',
+                level:'A'
+                }, {
+                classify: '环境报警',
+                name: 'B1F-5#变压器房 - B1-BDS-7',
+                alarm: '室温过高',
+                code:'1055',
+                level:'B'
+                }, {
+                classify: '环境报警',
+                name: 'B2F-8#排风机房 - B2-PFJF-8',
+                alarm: '室温过高',
+                code:'1055',
+                level:'B'
+                }, {
+                classify: '--',
+                name: 'B2F-5#排风机房 - B2-PFJF-5',
+                alarm: '室温过高',
+                code:'1055',
+                level:'B'
+                }, {
+                classify: '安全报警',
+                name: 'B2F-7#排风机房 - B2-PFJF-7',
+                alarm: '室温过高',
+                code:'1055',
+                level:'B'
+            }],
+            multipleSelection: [],
+            currentPage:10,
+            userData: [],
+            selectBoxIdArr: [], //表格多选的alarm的id数组      
+        }
+    },
+    components:{
+        manageNote,
+        alarmCode
+    },
+    methods:{
+        handleChange(value) {
+            console.log(value);
+        },
+        handleSelectionChange(arr) {
+            this.selectBoxIdArr = arr;
+        },
+        handleSizeChange(val) {
+        console.log(`每页 ${val} 条`);
+        },
+        handleCurrentChange(val) {
+            console.log(`当前页: ${val}`);
+        },
+        manageUser() {
+            this.dialogVisible = false;
+            this.manageDialogVisible = !this.manageDialogVisible
+        },
+        setUser() {
+            if (this.selectBoxIdArr.length) {
+               this.dialogVisible = true
+            } else {
+                this.$message({
+                    message: '请选择报警',
+                    type: 'warning'
+                })
+            }
+        },
+        pageChanged() {}
+    }
+}
+</script>
+
+<style lang="less" scoped>
+.alarm-notes{
+    .select-list{
+        padding: 0 10px 10px 10px;
+        // border-bottom: 1px solid #c2cedb;
+        background: #fff;
+        .item{
+            margin-top: 10px;
+            margin-right: 5px;
+        }
+        .btn-al{
+           margin-top: 10px;
+           margin-right: 5px;
+           display: inline-block; 
+        }  
+    }
+    .sg-table{
+        margin:10px 0;
+        padding:10px;
+        background:#fff;
+        .check-note{
+            margin-left: 50px;
+        }
+        .btn-alarm{
+            width: 200px;
+            float: right;
+            margin-bottom: 10px;
+        }
+        th{
+            text-align: center;
+        }
+    }
+    .footer-pagination{
+        text-align: center;
+    }
+    .ul-box{
+        min-height: 300px;
+    }
+}
+</style>
+<style lang="less">
+.alarm-notes{
+  .el-dialog__header{
+      text-align: center;
+  }
+  .el-dialog__body{
+      padding-top: 10px;
+  }
+}
+</style>
+

+ 99 - 0
src/demo/test/zhulz/manageNote.vue

@@ -0,0 +1,99 @@
+<template>
+  <div class="manage-note">
+    <div class="box" v-if="isrefresh">
+      <el-table :data="tableData" style="width: 100%" border> 
+        <el-table-column label="姓名" align="center">
+          <template slot-scope="scope">
+            <el-input v-if="scope.row.edit" v-model.trim="scope.row.name" size="small" placeholder="请输入姓名"/>
+            <span v-else>{{scope.row.name}}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="手机号" align="center">
+          <template slot-scope="scope">
+            <el-input v-if="scope.row.edit" v-model.trim="scope.row.phone" size="small" placeholder="请输入手机号码"/>
+            <span v-else>{{scope.row.phone}}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="邮箱地址" align="center">
+          <template slot-scope="scope">
+            <el-input v-if="scope.row.edit" v-model.trim="scope.row.email" size="small" placeholder="请输入邮箱地址"/>
+            <span v-else>{{scope.row.email}}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" width="150" align="center">
+          <template slot-scope="scope">
+            <p v-if="scope.row.edit">
+              <el-button type="text" size="small" @click="save(scope.row)">保存</el-button>
+              <el-button type="text" size="small" class="gray" @click="cancel(scope)">取消</el-button>
+            </p>
+            <p v-else>
+              <el-button type="text" size="small" class="red" @click="del(scope)">删除人员</el-button>
+              <el-button type="text" size="small" @click="edit(scope.row)">编辑个人信息</el-button>
+            </p>
+          </template>
+        </el-table-column>
+      </el-table>
+      <p>
+        <el-button type="primary" style="margin-top:10px" icon="el-icon-setting" @click="addUser">添加人员</el-button>
+      </p>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  components: {
+
+  },
+
+  mixins: [],
+
+  props: {
+
+  },
+
+  data () {
+    return {
+      tableData: [],
+      isrefresh: true,
+    }
+  },
+
+  computed: {
+
+  },
+
+  mounted() {
+
+  },
+
+  methods: {
+    addUser() {
+        this.tableData.push(this.initUser());        
+    },
+    initUser() {
+        return {name: "", phone: "", email: "", edit: true};
+    },
+    save(){},
+    // 取消 编辑取消or新建取消
+    cancel(scope) {
+        if(scope.row.id) {
+            scope.row.edit = false;
+        } else {
+            this.tableData.splice(scope.$index, 1)
+        }
+    },
+    // 编辑
+    edit(row) {
+        row.edit = true;
+    }
+  },
+
+}
+</script>
+
+<style scoped lang="less" >
+.manage-note{
+
+}
+</style>

+ 152 - 0
src/demo/views/form/FormPageDemo.vue

@@ -0,0 +1,152 @@
+<template>
+    <div class='input-form'>
+        <el-form :model='ruleForm' :rules='rules' ref='ruleForm'>
+            <el-form-item label='活动名称' prop='name'>
+                <el-input v-model='ruleForm.name'></el-input>
+            </el-form-item>
+            <el-form-item label='活动区域' prop='region'>
+                <el-select v-model='ruleForm.region' placeholder='请选择活动区域'>
+                    <el-option label='区域一' value='shanghai'></el-option>
+                    <el-option label='区域二' value='beijing'></el-option>
+                </el-select>
+            </el-form-item>
+            <el-form-item label='活动时间' required>
+                <el-col :span='6'>
+                    <el-form-item prop='date1'>
+                        <el-date-picker type='date' placeholder='选择日期' v-model='ruleForm.date1' style='width: 100%;'></el-date-picker>
+                    </el-form-item>
+                </el-col>
+                <el-col :span='6'>
+                    <el-form-item prop='date2'>
+                        <el-time-picker
+                            type='fixed-time'
+                            placeholder='选择时间'
+                            v-model='ruleForm.date2'
+                            style='width: 100%;'
+                        ></el-time-picker>
+                    </el-form-item>
+                </el-col>
+            </el-form-item>
+
+            <el-form-item label='活动时间' required>
+                <el-col :span='6'>
+                    <el-form-item prop='date1'>
+                        <el-date-picker type='date' placeholder='选择日期' v-model='ruleForm.date1' style='width: 100%;'></el-date-picker>
+                    </el-form-item>
+                </el-col>
+                <el-col :span='6'>
+                    <el-form-item prop='date2'>
+                        <el-time-picker
+                            type='fixed-time'
+                            placeholder='选择时间'
+                            v-model='ruleForm.date2'
+                            style='width: 100%;'
+                        ></el-time-picker>
+                    </el-form-item>
+                </el-col>
+            </el-form-item>
+
+            <el-form-item label='即时配送' prop='delivery'>
+                <el-switch on-text off-text v-model='ruleForm.delivery'></el-switch>
+            </el-form-item>
+            <el-form-item label='活动性质' prop='type'>
+                <el-checkbox-group v-model='ruleForm.type'>
+                    <el-checkbox label='美食/餐厅线上活动' name='type'></el-checkbox>
+                    <el-checkbox label='地推活动' name='type'></el-checkbox>
+                    <el-checkbox label='线下主题活动' name='type'></el-checkbox>
+                    <el-checkbox label='单纯品牌曝光' name='type'></el-checkbox>
+                </el-checkbox-group>
+            </el-form-item>
+            <el-form-item label='特殊资源' prop='resource'>
+                <el-radio-group v-model='ruleForm.resource'>
+                    <el-radio label='线上品牌商赞助'></el-radio>
+                    <el-radio label='线下场地免费'></el-radio>
+                </el-radio-group>
+            </el-form-item>
+            <el-form-item label='活动形式' prop='desc'>
+                <el-input type='textarea' v-model='ruleForm.desc'></el-input>
+            </el-form-item>
+            <el-form-item>
+                <el-button type='primary' @click='submitForm("ruleForm")'>立即创建</el-button>
+                <el-button @click='resetForm("ruleForm")'>重置</el-button>
+            </el-form-item>
+        </el-form>
+    </div>
+</template>
+<script>
+export default {
+    name: 'FormPageDemo',
+    props: [],
+    components: {},
+    data() {
+        return {
+            imagesArr: [
+                'http://service.sagacloud.cn:28888/image-service/common/file_get?systemId=saas&key=业主管理1537929021391.png'
+            ],
+            ruleForm: {
+                name: '',
+                region: '',
+                date1: '',
+                date2: '',
+                delivery: false,
+                type: [],
+                resource: '',
+                desc: ''
+            },
+            rules: {
+                name: [
+                    { required: true, message: '请输入活动名称', trigger: 'blur' },
+                    { min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
+                ],
+                region: [{ required: true, message: '请选择活动区域', trigger: 'change' }],
+                date1: [
+                    {
+                        type: 'date',
+                        required: true,
+                        message: '请选择日期',
+                        trigger: 'change'
+                    }
+                ],
+                date2: [
+                    {
+                        type: 'date',
+                        required: true,
+                        message: '请选择时间',
+                        trigger: 'change'
+                    }
+                ],
+                type: [
+                    {
+                        type: 'array',
+                        required: true,
+                        message: '请至少选择一个活动性质',
+                        trigger: 'change'
+                    }
+                ],
+                resource: [{ required: true, message: '请选择活动资源', trigger: 'change' }],
+                desc: [{ required: true, message: '请填写活动形式', trigger: 'blur' }]
+            }
+        }
+    },
+    methods: {
+        imagesChange(keys) {
+            this.imagesArr = keys
+        },
+        submitForm(formName) {
+            this.$refs[formName].validate(valid => {
+                if (valid) {
+                    alert('submit!')
+                } else {
+                    console.log('error submit!!')
+                    return false
+                }
+            })
+        },
+        resetForm(formName) {
+            this.$refs[formName].resetFields()
+        }
+    }
+}
+</script>
+<style lang='scss' scoped>
+</style>

+ 122 - 0
src/demo/views/table/TablePageDemo.vue

@@ -0,0 +1,122 @@
+<template>
+    <table-page-template>
+        <el-form slot='form' :inline='true' :model='formInline' size='mini'>
+            <el-form-item label='审批人'>
+                <el-input v-model='formInline.user' placeholder='审批人'></el-input>
+            </el-form-item>
+            <el-form-item label='活动区域'>
+                <el-select v-model='formInline.region' placeholder='活动区域'>
+                    <el-option label='区域一' value='shanghai'></el-option>
+                    <el-option label='区域二' value='beijing'></el-option>
+                </el-select>
+            </el-form-item>
+            <el-form-item>
+                <el-button type='primary' @click='query'>查询</el-button>
+            </el-form-item>
+            <el-form-item label='审批人'>
+                <el-input v-model='formInline.user' placeholder='审批人'></el-input>
+            </el-form-item>
+            <el-form-item label='备选项'>
+                <el-radio-group v-model='radio2'>
+                    <el-radio :label='3'>备选项3</el-radio>
+                    <el-radio :label='6'>备选项6</el-radio>
+                    <el-radio :label='9'>备选项9</el-radio>
+                </el-radio-group>
+            </el-form-item>
+            <el-form-item label='审批人'>
+                <el-input v-model='formInline.user' placeholder='审批人'></el-input>
+            </el-form-item>
+            <el-form-item label='复选框'>
+                <el-checkbox-group v-model='checkList' @change='checkListChange'>
+                    <el-checkbox label='复选框 A'>复选框 1</el-checkbox>
+                    <el-checkbox label='复选框 B'></el-checkbox>
+                    <el-checkbox label='复选框 C'></el-checkbox>
+                    <el-checkbox label='禁用' disabled></el-checkbox>
+                    <el-checkbox label='选中且禁用' disabled></el-checkbox>
+                </el-checkbox-group>
+            </el-form-item>
+        </el-form>
+        <el-table
+            slot='table'
+            ref='multipleTable'
+            :data='tableData3'
+            border
+            tooltip-effect='dark'
+            style='width: 100%'
+            @selection-change='handleSelectionChange'
+        >
+            <el-table-column type='selection' width='55'></el-table-column>
+            <el-table-column label='日期' width='120'>
+                <template slot-scope='scope'>{{ scope.row.date }}</template>
+            </el-table-column>
+            <el-table-column prop='name' label='姓名' width='120'></el-table-column>
+            <el-table-column prop='address' label='地址' show-overflow-tooltip></el-table-column>
+        </el-table>
+        <base-pagination :total='456' @pageChanged='pageChanged' slot='pagination'></base-pagination>
+    </table-page-template>
+</template>
+<script>
+export default {
+    name: 'DemoTable',
+    data() {
+        return {
+            radio2: 3,
+            checkList: ['选中且禁用', '复选框 A'],
+            formInline: {
+                user: '',
+                region: ''
+            },
+            tableData3: [],
+            tableData: [
+                {
+                    date: '2016-05-03',
+                    name: '王小虎',
+                    address: '上海市普陀区金沙江路 1518 弄'
+                },
+                {
+                    date: '2016-05-02',
+                    name: '王小虎',
+                    address: '上海市普陀区金沙江路 1518 弄'
+                }
+            ],
+            multipleSelection: [],
+            total: 456
+        }
+    },
+    methods: {
+        onSubmit() {
+            console.log('submit!')
+        },
+        checkListChange() {
+            console.log('checkListChange ' + JSON.stringify(this.checkList))
+        },
+        handleSelectionChange(val) {
+            console.log('handleSelectionChange --> ' + val)
+            this.multipleSelection = val
+        },
+        handleSizeChange(size) {
+            console.log('handleSizeChange --> ' + size)
+        },
+        handleCurrentChange(page) {
+            console.log('handleCurrentChange --> ' + page)
+        },
+        query() {
+            this.postJson('/server/getTableData', {}, resp => {
+                console.log(resp)
+            })
+        },
+        pageChanged(page, size) {
+            console.log('pageChanged size=' + size + ', page = ' + page)
+        }
+    },
+    created() {
+        for (let i = 0; i < 50; i++) {
+            this.tableData3.push({
+                date: '2016-05-03',
+                name: '王小虎',
+                address: '上海市普陀区金沙江路 1518 弄'
+            })
+        }
+    }
+}
+</script>

+ 53 - 0
src/framework/components/BasePagination.vue

@@ -0,0 +1,53 @@
+<template>
+    <el-pagination
+        @size-change='handleSizeChange'
+        @current-change='handleCurrentChange'
+        :current-page='currentPages?currentPages:pageInfo.currentPage'
+        :page-sizes='pageInfo.pageSizes'
+        :page-size='pageInfo.pageSize'
+        :layout='pageInfo.layout'
+        :total='pageInfo.total'
+        style='text-align: center'
+    ></el-pagination>
+</template>
+<script>
+export default {
+    name: 'base-pagination',
+    props: ['total', 'customconfig', 'currentPages'],
+    data() {
+        var vm = this
+        let pageInfo = this.initPagination()
+        if (!!this.total) {
+            pageInfo.total = this.total
+        }
+        //分页器可添加自定义的配置,在引用的时候,需要传递参数,如果有参数,就合并
+        if (!!this.customconfig) {
+            pageInfo = Object.assign(pageInfo, this.customconfig)
+        }
+        return {
+            pageInfo: pageInfo
+        }
+    },
+    methods: {
+        handleSizeChange: function(size) {
+            this.pageInfo.pageSize = size
+            this.$emit('pageChanged', this.pageInfo.currentPage, this.pageInfo.pageSize)
+        },
+        handleCurrentChange: function(currentPage) {
+            this.pageInfo.currentPage = currentPage
+            this.$emit('pageChanged', this.pageInfo.currentPage, this.pageInfo.pageSize)
+        }
+    },
+    watch: {
+        total: function() {
+            this.pageInfo.total = this.total
+        },
+        currentPages: {
+            immediate: true,
+            handler(val) {
+                this.pageInfo.currentPage = val
+            }
+        }
+    }
+}
+</script>

+ 171 - 13
src/framework/layout/Login.vue

@@ -1,24 +1,182 @@
 <template>
 <template>
-    <div>
-        <h4>Login</h4>
+    <div class='login-container'>
+        <el-form
+            class='card-box login-form'
+            autocomplete='on'
+            :model='loginForm'
+            :rules='loginRules'
+            ref='loginForm'
+            label-position='left'
+        >
+            <h3 class='title'>系统登录</h3>
+            <el-form-item prop='username'>
+                <span class='svg-container svg-container_login'>
+                    <i class='el-icon-fa-user-o'></i>
+                </span>
+                <el-input name='username' type='text' v-model='loginForm.username' autocomplete='on' placeholder='邮箱'/>
+            </el-form-item>
+            <el-form-item prop='password'>
+                <span class='svg-container'>
+                    <i class='el-icon-fa-key'></i>
+                </span>
+                <el-input
+                    name='password'
+                    type='password'
+                    v-model='loginForm.password'
+                    placeholder='密码'
+                    @keyup.enter.native.prevent='handleLogin'
+                />
+            </el-form-item>
+            <el-button
+                type='primary'
+                style='width:100%;margin-bottom:30px;'
+                :loading='loading'
+                @click.native.prevent='handleLogin'
+            >登录</el-button>
+        </el-form>
     </div>
     </div>
 </template>
 </template>
 <script>
 <script>
+function isvalidUsername(val) {
+    return true
+}
+import frameworkApi from '@/api/framework'
+import { mapActions, mapGetters } from 'vuex'
 export default {
 export default {
-    name: 'Login',
-    props: [],
+    components: {},
+    name: 'login',
     data() {
     data() {
-        return {}
+        const validateUsername = (rule, value, callback) => {
+            if (!isvalidUsername(value)) {
+                callback(new Error('请输入正确的用户名'))
+            } else {
+                callback()
+            }
+        }
+        const validatePassword = (rule, value, callback) => {
+            if (value.length < 6) {
+                callback(new Error('密码不能小于6位'))
+            } else {
+                callback()
+            }
+        }
+        return {
+            loginForm: {
+                username: 'admin',
+                password: '123456'
+            },
+            loginRules: {
+                username: [
+                    {
+                        required: true,
+                        trigger: 'blur',
+                        validator: validateUsername
+                    }
+                ],
+                password: [
+                    {
+                        required: true,
+                        trigger: 'blur',
+                        validator: validatePassword
+                    }
+                ]
+            },
+            loading: false
+        }
     },
     },
-    computed: {},
-    methods: {},
-    created() {
-        console.log('--------------------- Login created')
-        window.location = ''
+    computed: {
+        //...mapGetters(['beforeUrl'])
     },
     },
-    mounted() {},
-    components: {}
+    methods: {
+        async handleLogin() {
+            let vm = this
+            vm.$refs.loginForm.validate(valid => {
+                if (valid) {
+                    let username = this.loginForm.username
+                    let password = this.loginForm.password
+                    frameworkApi.login(username, password).then(resp => {
+                        console.log('login result => ', resp)
+                        if (resp.result == 'success') {
+                            this.$store.dispatch('layout/loadUserInfo').then(resp => {
+                                console.log('store dispatch result ', resp)
+                                if (resp.result == 'success') {
+                                    vm.$router.push('/demo/table', () => {})
+                                } else {
+                                }
+                            })
+                        } else {
+                        }
+                    })
+                } else {
+                    console.log('error submit!!')
+                    return false
+                }
+            })
+        }
+    }
 }
 }
 </script>
 </script>
-<style lang='scss' scoped>
+<style rel="stylesheet/scss" lang="scss">
+$bg: #2d3a4b;
+$dark_gray: #889aa4;
+$light_gray: #eee;
+.login-container {
+    height: 100vh;
+    background-color: $bg;
+    input:-webkit-autofill {
+        -webkit-box-shadow: 0 0 0px 1000px #293444 inset !important;
+        -webkit-text-fill-color: #fff !important;
+    }
+    input {
+        background: transparent;
+        border: 0px;
+        -webkit-appearance: none;
+        border-radius: 0px;
+        padding: 12px 5px 12px 15px;
+        color: $light_gray;
+        height: 47px;
+    }
+    .el-input {
+        display: inline-block;
+        height: 47px;
+        width: 85%;
+    }
+    .tips {
+        font-size: 14px;
+        color: #fff;
+        margin-bottom: 10px;
+    }
+    .svg-container {
+        padding: 6px 5px 6px 15px;
+        color: $dark_gray;
+        vertical-align: middle;
+        width: 30px;
+        display: inline-block;
+        &_login {
+            font-size: 20px;
+        }
+    }
+    .title {
+        font-size: 26px;
+        font-weight: 400;
+        color: $light_gray;
+        margin: 0px auto 40px auto;
+        text-align: center;
+        font-weight: bold;
+    }
+    .login-form {
+        position: absolute;
+        left: 0;
+        right: 0;
+        width: 400px;
+        padding: 35px 35px 15px 35px;
+        margin: 120px auto;
+    }
+    .el-form-item {
+        border: 1px solid rgba(255, 255, 255, 0.1);
+        background: rgba(0, 0, 0, 0.1);
+        border-radius: 5px;
+        color: #454545;
+    }
+}
 </style>
 </style>

+ 10 - 6
src/framework/layout/Main.vue

@@ -1,6 +1,7 @@
 <template>
 <template>
     <div id='page-main' v-bind:class='{"page-sidebar-closed": sidebarClosed}'>
     <div id='page-main' v-bind:class='{"page-sidebar-closed": sidebarClosed}'>
         <page-header></page-header>
         <page-header></page-header>
+
         <div id='page-container' class='page-container'>
         <div id='page-container' class='page-container'>
             <page-sidebar></page-sidebar>
             <page-sidebar></page-sidebar>
 
 
@@ -11,12 +12,15 @@
                         <el-breadcrumb-item v-for='(b, index) in breadcrumb' :key='index'>{{b.label}}</el-breadcrumb-item>
                         <el-breadcrumb-item v-for='(b, index) in breadcrumb' :key='index'>{{b.label}}</el-breadcrumb-item>
                     </el-breadcrumb>
                     </el-breadcrumb>
                 </div>
                 </div>
-                <el-scrollbar tag="div" wrapClass="content-scrollbar" style="height:100%;">
-                    <router-view class='page-content'/>
-                </el-scrollbar>
+                <!-- <router-view class='page-content'/> -->
+
+                <keep-alive>
+                    <router-view v-if='$route.meta.keepAlive' class='page-content'></router-view>
+                </keep-alive>
+                <router-view v-if='!$route.meta.keepAlive' class='page-content'></router-view>
             </div>
             </div>
         </div>
         </div>
-        <!-- <div class='page-footer'>footer</div> -->
+        <div class='page-footer'>footer</div>
     </div>
     </div>
 </template>
 </template>
 <script>
 <script>
@@ -53,8 +57,8 @@ export default {
         }
         }
     },
     },
     created() {
     created() {
-        // console.log('--------------------- Main created')
-        // console.log(this.$store.getters.flag)
+        console.log('--------------------- Main created')
+        console.log(this.$store.getters.flag)
     },
     },
     mounted() {
     mounted() {
         this.windwoResize()
         this.windwoResize()

+ 10 - 14
src/framework/layout/PageHeader.vue

@@ -1,20 +1,16 @@
 <template>
 <template>
     <div class='page-header'>
     <div class='page-header'>
-
         <div id='page-header-logo' class='page-logo'>
         <div id='page-header-logo' class='page-logo'>
-            <a class='logo-big' href='/'>
-                <img src='@/assets/logo.jpg' alt='logo' class='logo-default'>
-            </a> 
-            <a class='logo-small' href='/'>
-                <img src='@/assets/logo-small.jpg' alt='logo' class='logo-default'>
-            </a>           
-        </div>
-        <div id='page-header-data-menu' class='data-menu'>
+            <a href='index.html'>
+                <img src='@/assets/logo.png' alt='logo' class='logo-default'>
+            </a>
             <div class='menu-toggler sidebar-toggler' @click.stop='toggleSidebar'>
             <div class='menu-toggler sidebar-toggler' @click.stop='toggleSidebar'>
                 <span>
                 <span>
-                    <i class='el-icon-fa-bars icon-arrows'></i>
+                    <i class='el-icon-fa-bars'></i>
                 </span>
                 </span>
             </div>
             </div>
+        </div>
+        <div id='page-header-data-menu' class='data-menu'>
             <el-select v-model='selectedProjectId' placeholder='请选择'>
             <el-select v-model='selectedProjectId' placeholder='请选择'>
                 <el-option v-for='item in projects' :key='item.id' :label='item.name' :value='item.id'></el-option>
                 <el-option v-for='item in projects' :key='item.id' :label='item.name' :value='item.id'></el-option>
             </el-select>
             </el-select>
@@ -34,14 +30,14 @@
     </div>
     </div>
 </template>
 </template>
 <script>
 <script>
-import authutils from '@/utils/authutils'
+import frameworkApi from '@/api/framework'
 import { mapGetters, mapMutations } from 'vuex'
 import { mapGetters, mapMutations } from 'vuex'
 export default {
 export default {
     name: 'PageHeader',
     name: 'PageHeader',
     props: [],
     props: [],
     data() {
     data() {
         return {
         return {
-            selectedProjectId: 'Pj1101080002'
+            selectedProjectId: null
         }
         }
     },
     },
     computed: {
     computed: {
@@ -61,12 +57,12 @@ export default {
         userMenuCommand(cmd) {
         userMenuCommand(cmd) {
             console.log('userMenuCommand ', cmd)
             console.log('userMenuCommand ', cmd)
             if (cmd == 'logout') {
             if (cmd == 'logout') {
-                authutils.toLogout()
+                frameworkApi.toLogout()
             }
             }
         }
         }
     },
     },
     created() {
     created() {
-        // console.log('--------------------- PageHeader created')
+        console.log('--------------------- PageHeader created')
         this.selectedProjectId = this.currentProjectId
         this.selectedProjectId = this.currentProjectId
     },
     },
     mounted() {},
     mounted() {},

+ 29 - 31
src/framework/layout/PageSidebar.vue

@@ -1,43 +1,42 @@
 <template>
 <template>
-    <div class='page-sidebar-wrapper'>
+    <div id='page-sidebar-wrapper' class='page-sidebar-wrapper'>
         <el-menu
         <el-menu
             :collapse='sidebarClosed'
             :collapse='sidebarClosed'
             :default-active='sidebarSelected'
             :default-active='sidebarSelected'
             @open='handleOpen'
             @open='handleOpen'
             @close='handleClose'
             @close='handleClose'
             @select='menuSelect'
             @select='menuSelect'
-            text-color='#333333'
-            active-text-color='#5BA7FF'
+            background-color='#364150'
+            text-color='#fff'
+            active-text-color='#ffd04b'
             unique-opened
             unique-opened
             router
             router
+            class='sidebar-menu'
         >
         >
             <template v-for='menu in menus'>
             <template v-for='menu in menus'>
-                <!-- <div class='underline-box'> -->
-                    <el-submenu v-if='menu.children' :index='menu.path' :key='menu.path'>
-                        <template slot='title'>
-                            <i v-if='menu.icon' :class='"el-icon-fa "+ menu.icon'></i>
-                            <span>{{menu.name}}</span>
-                        </template>
-                        <template v-for='submenu in menu.children'>
-                                <el-menu-item :index='submenu.path' :key='submenu.path'>
-                                    <i v-if='submenu.icon' :class='"el-icon-fa "+ submenu.icon'></i>
-                                    <span slot='title'>{{submenu.name}}</span>
-                                </el-menu-item>
-                        </template>
-                    </el-submenu>
-                    <el-menu-item v-else :index='menu.path' :key='menu.path'>
+                <el-submenu v-if='menu.children' :index='menu.path' :key='menu.path' class='sidebar-menu-submenu'>
+                    <template slot='title'>
                         <i v-if='menu.icon' :class='"el-icon-fa "+ menu.icon'></i>
                         <i v-if='menu.icon' :class='"el-icon-fa "+ menu.icon'></i>
-                        <span slot='title'>{{menu.name}}</span>
-                    </el-menu-item>
-                    <!-- <p class='underline'></p> -->
-                <!-- </div> -->
+                        <span>{{menu.name}}</span>
+                    </template>
+                    <template v-for='submenu in menu.children'>
+                        <el-menu-item :index='submenu.path' :key='submenu.path' class='sidebar-menu-item'>
+                            <i v-if='submenu.icon' :class='"el-icon-fa "+ submenu.icon'></i>
+                            <span slot='title'>{{submenu.name}}</span>
+                        </el-menu-item>
+                    </template>
+                </el-submenu>
+                <el-menu-item v-else :index='menu.path' :key='menu.path' class='sidebar-menu-item'>
+                    <i v-if='menu.icon' :class='"el-icon-fa "+ menu.icon'></i>
+                    <span slot='title'>{{menu.name}}</span>
+                </el-menu-item>
             </template>
             </template>
         </el-menu>
         </el-menu>
     </div>
     </div>
 </template>
 </template>
 <script>
 <script>
 import { mapGetters, mapMutations } from 'vuex'
 import { mapGetters, mapMutations } from 'vuex'
-import authutils from '@/utils/authutils'
+import frameworkApi from '@/api/framework'
 export default {
 export default {
     name: 'PageSidebar',
     name: 'PageSidebar',
     props: [],
     props: [],
@@ -47,29 +46,28 @@ export default {
     computed: {
     computed: {
         ...mapGetters('layout', ['sidebarClosed', 'sidebarSelected', 'permissions']),
         ...mapGetters('layout', ['sidebarClosed', 'sidebarSelected', 'permissions']),
         menus() {
         menus() {
-            // console.log('*******************')
-            // console.log(this.permissions)
-            let menus = authutils.getMenus(this.permissions)
-            // console.log('sidebar menus ', menus)
+            console.log(this.permissions)
+            let menus = frameworkApi.getMenus(this.permissions)
+            console.log('sidebar menus ', menus)
             return menus
             return menus
         }
         }
     },
     },
     methods: {
     methods: {
         ...mapMutations('layout', ['setSidebarSelected']),
         ...mapMutations('layout', ['setSidebarSelected']),
         handleOpen(val) {
         handleOpen(val) {
-            // console.log('handleOpen------------- ', val)
+            console.log('handleOpen------------- ', val)
         },
         },
         handleClose(val) {
         handleClose(val) {
-            // console.log('handleClose------------- ', val)
+            console.log('handleClose------------- ', val)
         },
         },
         menuSelect(index, indexPath) {
         menuSelect(index, indexPath) {
             this.setSidebarSelected(index)
             this.setSidebarSelected(index)
-            // console.log('menu select ', index, indexPath)
+            console.log('menu select ', index, indexPath)
         }
         }
     },
     },
     created() {
     created() {
-        // console.log('--------------------- PageSidebar created')
-        // console.log('menus ', this.menus)
+        console.log('--------------------- PageSidebar created')
+        console.log('menus ', this.menus)
     },
     },
     mounted() {},
     mounted() {},
     components: {}
     components: {}

+ 5 - 46
src/framework/layout/layout-store.js

@@ -1,5 +1,5 @@
-import adminapi from '@/api/system/admin'
-import storage from '@/utils/storage'
+import frameworkApi from '@/api/framework'
+import storage from '@/framework/utils/storage'
 
 
 const KEY_MENU_SELECTED = 'menu_selected'
 const KEY_MENU_SELECTED = 'menu_selected'
 const KEY_PROJECT_SELECTED = 'global_project_selected'
 const KEY_PROJECT_SELECTED = 'global_project_selected'
@@ -11,9 +11,9 @@ export default {
         sidebarClosed: false,
         sidebarClosed: false,
         sidebarSelected: '', // sidebar选中的选项
         sidebarSelected: '', // sidebar选中的选项
         userInfo: { username: 'admin' },
         userInfo: { username: 'admin' },
-        permissions: {"system:role:delete": true, "system:role:create": true, "system:role:query": true, "system:role:setOpts": true},
+        permissions: { "system:role:delete": true, "system:role:create": true, "system:role:query": true, "system:role:setOpts": true },
         currentProjectId: null,
         currentProjectId: null,
-        projects: [{name: '新华创新大厦',id: 'Pj1101080002'}],
+        projects: [{ name: '新华创新大厦', id: 'Pj1101080002' }],
         breadcrumb: []
         breadcrumb: []
     },
     },
     getters: {
     getters: {
@@ -63,7 +63,7 @@ export default {
     actions: {
     actions: {
         loadUserInfo({ state }) {
         loadUserInfo({ state }) {
             return new Promise((resolve, reject) => {
             return new Promise((resolve, reject) => {
-                adminapi.loadUserInfo().then(resp => {
+                frameworkApi.loadUserInfo().then(resp => {
                     console.log('api load user info ', resp)
                     console.log('api load user info ', resp)
                     if (resp.result == 'success') {
                     if (resp.result == 'success') {
                         state.userInfo = { username: resp.username }
                         state.userInfo = { username: resp.username }
@@ -85,47 +85,6 @@ export default {
                     }
                     }
                     resolve(resp)
                     resolve(resp)
                 })
                 })
-                // let resp = {
-                //     result: 'success',
-                //     message: null,
-                //     projects: [
-                //         {
-                //             projId: 'Pj4419000006',
-                //             projName: '广东省东莞市市辖区0001项目',
-                //             projLocalName: '厚街万科城市广场',
-                //             longitude: '113.23',
-                //             latitude: '23.16',
-                //             distance: 500
-                //         }
-                //     ],
-                //     permissions: [
-                //         'system:role:delete',
-                //         'system:role:create',
-                //         'system:role:query',
-                //         'system:role:setOpts',
-                //         'system:role:update'
-                //     ],
-                //     username: 'fuguoyu'
-                // }
-                // if (resp.result == 'success') {
-                //     state.userInfo = { username: resp.username }
-                //     state.permissions = {}
-                //     if (resp.permissions) {
-                //         resp.permissions.forEach(p => (state.permissions[p] = true))
-                //     }
-                //     state.projects = []
-                //     if (resp.projects) {
-                //         resp.projects.forEach(proj =>
-                //             state.projects.push({
-                //                 id: proj.projId,
-                //                 name: proj.projLocalName
-                //             })
-                //         )
-                //     }
-                // } else {
-                //     state.userInfo = null
-                // }
-                // resolve(resp)
             })
             })
         },
         },
         setBreadcrumb: {
         setBreadcrumb: {

+ 12 - 17
src/plugins/components.js

@@ -1,12 +1,15 @@
-import BasePagination from '@/components/sagacloud/BasePagination'
+import store from '@/store'
+import BasePagination from '@/framework/components/BasePagination'
 import TableTemplate from '@/framework/template/TablePageTemplate'
 import TableTemplate from '@/framework/template/TablePageTemplate'
-import SgSelector from '@/components/sagacloud/SgSelector'
 //tools
 //tools
-import basicutils from '@/utils/basicutils'
-import httputils from '@/utils/httputils.js'
+import basicutils from '@/framework/utils/basicutils'
 
 
 export default {
 export default {
     install: function(Vue) {
     install: function(Vue) {
+        Vue.prototype.hasPermission = function(permission) {
+            return store.getters['layout/permissions'][permission]
+        }
+
         Vue.prototype.initPagination = function() {
         Vue.prototype.initPagination = function() {
             return {
             return {
                 pageSize: 10,
                 pageSize: 10,
@@ -18,26 +21,18 @@ export default {
                 params: {}
                 params: {}
             }
             }
         }
         }
+
         Vue.component('base-pagination', BasePagination)
         Vue.component('base-pagination', BasePagination)
         Vue.component('table-page-template', TableTemplate)
         Vue.component('table-page-template', TableTemplate)
-        Vue.component('sg-selector', SgSelector)
+
+        Vue.prototype.indexInArray = basicutils.indexInArray
+        Vue.prototype.itemInArray = basicutils.itemInArray
+        Vue.prototype.deleteInArray = basicutils.deleteInArray
 
 
         Vue.prototype.formatDate = function(date) {
         Vue.prototype.formatDate = function(date) {
             return basicutils.formatDateByPattern(date, 'yyyy-MM-dd HH:mm:ss')
             return basicutils.formatDateByPattern(date, 'yyyy-MM-dd HH:mm:ss')
         }
         }
 
 
-        Vue.prototype.hasPermission = function(promise) {
-            return basicutils.hasPermission(promise)
-        }
-
-        /**http plugins */
-        // 添加全局方法
-        Vue.prototype.getJson = httputils.getJson
-
-        Vue.prototype.postJson = httputils.postJson
-
-        Vue.prototype.download = httputils.download
-
         Vue.filter('formatDateForMillisecond', function(value) {
         Vue.filter('formatDateForMillisecond', function(value) {
             if (!value) return ''
             if (!value) return ''
             return basicutils.formatDateByPattern(new Date(value), 'yyyy-MM-dd')
             return basicutils.formatDateByPattern(new Date(value), 'yyyy-MM-dd')

+ 110 - 77
src/framework/style/layout.scss

@@ -1,9 +1,10 @@
 @import './theme.scss';
 @import './theme.scss';
 
 
-$pageHeaderHeight: 60px;
+$pageHeaderHeight: 50px;
 
 
-$pageSidebarWidth: 220px;
-$pageSidebarClosedWidth: 60px;
+$pageSidebarWidth: 235px;
+$pageSidebarClosedWidth: 64px;
+$pageSidebarItemHeight: 40px;
 
 
 $pageFooterHeight: 40px;
 $pageFooterHeight: 40px;
 
 
@@ -47,32 +48,10 @@ body {
             overflow-y: auto;
             overflow-y: auto;
             flex-grow: 0;
             flex-grow: 0;
             flex-shrink: 0;
             flex-shrink: 0;
-            overflow: hidden;
-            border-right: 1px solid #c2cedb;
-            // .underline-box {
-            //     position: relative;
-            //     overflow: hidden;
-            //     .underline {
-            //         position: absolute;
-            //         width: 180px;
-            //         height: 1px;
-            //         background-color: #C2CEDB;
-            //         left: 20px;
-            //         bottom: -14px;
-            //     }
-            // }
         }
         }
         .page-content-wrapper {
         .page-content-wrapper {
             flex-grow: 1;
             flex-grow: 1;
             flex-shrink: 1;
             flex-shrink: 1;
-            .content-scrollbar {
-                height: calc(100vh - 108px);
-                .el-scrollbar__bar {
-                    &.is-vertical {
-                        display: none;
-                    }
-                }
-            }
         }
         }
     }
     }
 
 
@@ -93,40 +72,29 @@ body {
         flex-grow: 0;
         flex-grow: 0;
         flex-shrink: 0;
         flex-shrink: 0;
 
 
-        width: 220px;
+        padding-left: 20px;
+        padding-right: 20px;
+        width: 195px;
 
 
         display: inline-flex;
         display: inline-flex;
         flex-direction: row;
         flex-direction: row;
         justify-content: space-between;
         justify-content: space-between;
-        > .logo-big {
+        > a {
             display: inline-block;
             display: inline-block;
-            margin-top: 14px;
-            margin-left: 66px;
+            .logo-default {
+                margin: 18px 0 0;
+            }
         }
         }
-        > .logo-small {
-            display: none;
+        .menu-toggler.sidebar-toggler {
+            margin: 15.5px 0 0;
         }
         }
     }
     }
     .data-menu {
     .data-menu {
         flex-grow: 0;
         flex-grow: 0;
         flex-shrink: 1;
         flex-shrink: 1;
-        width: 290px;
+        width: 240px;
         height: 100%;
         height: 100%;
         line-height: $pageHeaderHeight;
         line-height: $pageHeaderHeight;
-        display: flex;
-        justify-content: center;
-        .menu-toggler {
-            margin-right: 10px;
-            .icon-arrows {
-                display: inline-block;
-                width: 24px;
-                height: 24px;
-                margin-left: 10px;
-                line-height: px;
-                text-align: center;
-                font-size: 20px;
-            }
-        }
         .data-menu-dropdown {
         .data-menu-dropdown {
             height: 100%;
             height: 100%;
             line-height: $pageHeaderHeight;
             line-height: $pageHeaderHeight;
@@ -157,20 +125,32 @@ body {
 #page-main .page-container {
 #page-main .page-container {
     .page-sidebar-wrapper {
     .page-sidebar-wrapper {
         .el-menu {
         .el-menu {
-            border-right: none;
-            .el-submenu__title,
+        }
+    }
+}
+
+#page-main .page-container #page-sidebar-wrapper {
+    .sidebar-menu.el-menu {
+        border-right: none;
+        .el-submenu {
             .el-menu-item {
             .el-menu-item {
-                height: 40px;
-                line-height: 40px;
-            }
-            .el-menu--inline {
-                background: #eefaff;
-                border-left: 4px solid #5ba7ff;
+                height: $pageSidebarItemHeight;
+                line-height: $pageSidebarItemHeight;
             }
             }
         }
         }
     }
     }
 }
 }
 
 
+/** sidebar 弹框 */
+.el-menu--vertical {
+    .el-menu.el-menu--popup.el-menu--popup-right-start {
+        .el-menu-item.sidebar-menu-item {
+            height: $pageSidebarItemHeight;
+            line-height: $pageSidebarItemHeight;
+        }
+    }
+}
+
 #page-main .page-container .page-content-wrapper {
 #page-main .page-container .page-content-wrapper {
     margin: 0px 20px 10px 10px;
     margin: 0px 20px 10px 10px;
 
 
@@ -184,7 +164,7 @@ body {
         height: 30px;
         height: 30px;
         padding: 0 20px;
         padding: 0 20px;
         margin-bottom: 10px;
         margin-bottom: 10px;
-        border-bottom: 1px solid #c2cedb;
+        border-bottom: 1px solid #333;
         .el-breadcrumb {
         .el-breadcrumb {
             font-size: 14px;
             font-size: 14px;
             line-height: 30px;
             line-height: 30px;
@@ -197,27 +177,33 @@ body {
     }
     }
 }
 }
 
 
-#page-main #page-container #page-content-wrapper .page-content.page-table-template {
+// #page-main #page-container #page-content-wrapper .page-content.page-table-template {
+#page-main #page-container #page-content-wrapper .page-table-template {
     display: flex;
     display: flex;
     flex-direction: column;
     flex-direction: column;
     justify-content: flex-start;
     justify-content: flex-start;
+    align-items: stretch;
+
+    flex-grow: 1;
+    flex-shrink: 1;
 
 
-    .query-form {
+    > .query-form {
         flex-grow: 0;
         flex-grow: 0;
         flex-shrink: 0;
         flex-shrink: 0;
     }
     }
-    .data-table {
+    > .data-table {
         flex-grow: 1;
         flex-grow: 1;
         flex-shrink: 1;
         flex-shrink: 1;
+        overflow-x: auto;
         overflow-y: auto;
         overflow-y: auto;
     }
     }
-    .data-table-pagination {
+    > .data-table-pagination {
         flex-grow: 0;
         flex-grow: 0;
         flex-shrink: 0;
         flex-shrink: 0;
     }
     }
 }
 }
 
 
-#page-main #page-container #page-content-wrapper .page-content .query-form {
+#page-main #page-container #page-content-wrapper .page-content > .query-form {
     padding: 5px 10px 0px 10px;
     padding: 5px 10px 0px 10px;
     margin-bottom: 10px;
     margin-bottom: 10px;
     .el-form {
     .el-form {
@@ -239,18 +225,30 @@ body {
 }
 }
 
 
 #page-main #page-container #page-content-wrapper .page-content .data-table {
 #page-main #page-container #page-content-wrapper .page-content .data-table {
-    .el-table__header-wrapper {
-        .el-table__header {
-            thead tr th {
+}
+
+// #page-main #page-container #page-content-wrapper .page-content  .data-table {
+.data-table {
+    position: relative;
+
+    > .el-table {
+        position: absolute;
+        .el-table__header-wrapper {
+            .el-table__header {
+                thead tr th {
+                }
             }
             }
         }
         }
-    }
-    .el-table__body-wrapper {
-        .el-table__body {
-            tr td {
-                padding: 6px 0;
-                .cell {
-                    line-height: 20px;
+        .el-table__body-wrapper {
+            .el-table__body {
+                tr td {
+                    padding: 6px 0;
+                    .cell {
+                        line-height: 20px;
+                    } 
+                    &.ttt{
+                        padding: 2px 0;
+                    }                   
                 }
                 }
             }
             }
         }
         }
@@ -283,13 +281,9 @@ body {
             padding-left: 20px;
             padding-left: 20px;
             padding-right: 20px;
             padding-right: 20px;
             width: 20px;
             width: 20px;
-            > .logo-big {
+            > a {
                 display: none;
                 display: none;
             }
             }
-            > .logo-small {
-                display: inline-block;
-                margin-top: 14px;
-            }
         }
         }
     }
     }
     .page-container {
     .page-container {
@@ -328,8 +322,8 @@ body {
         }
         }
         .page-container {
         .page-container {
             display: flex;
             display: flex;
-            flex-direction: column; /* 垂直,从上到下 */
-            justify-content: flex-start; /* 垂直 左对齐 */
+            flex-direction: column;
+            justify-content: flex-start;
 
 
             .page-sidebar-wrapper {
             .page-sidebar-wrapper {
                 width: 100%;
                 width: 100%;
@@ -345,3 +339,42 @@ body {
         }
         }
     }
     }
 }
 }
+
+#page-main #page-container #page-content-wrapper .box {
+    display: flex;
+    flex-direction: column;
+
+    .el-tabs {
+        flex-grow: 1;
+        flex-shrink: 1;
+
+        display: flex;
+        flex-direction: column;
+
+        .el-tabs__header {
+            flex-grow: 0;
+            flex-shrink: 0;
+        }
+        .el-tabs__content {
+            flex-grow: 1;
+            flex-shrink: 1;
+
+            display: flex;
+            flex-direction: column;
+
+            .el-tab-pane {
+                height: 100%;
+                // flex-grow: 1;
+                // flex-shrink: 1;
+
+                display: flex;
+                flex-direction: column;
+
+                // // > div {
+                // //     flex-grow: 1;
+                // //     flex-shrink: 1;
+                // // }
+            }
+        }
+    }
+}

+ 68 - 33
src/framework/style/theme.scss

@@ -1,61 +1,79 @@
-$themeColor: #5BA7FF;
+$colorWhite: #fff;
+
+$pageHeaderBackground: #2b3643;
 .body {
 .body {
-    // color: #333;
+    color: #333;
 }
 }
-
-#app {
+#app #page-main {
     .page-header {
     .page-header {
-        background: $themeColor;
+        background: $pageHeaderBackground;
+
         .page-logo {
         .page-logo {
-            background: #fff;
+            .menu-toggler.sidebar-toggler {
+                color: $colorWhite;
+            }
         }
         }
+
         .data-menu {
         .data-menu {
             .data-menu-dropdown {
             .data-menu-dropdown {
-                color: #fff;
-            }
-            .icon-arrows {
-                background: #fff;
-                color: $themeColor;
+                color: $colorWhite;
             }
             }
-            .el-select {   
-                .el-input--suffix .el-input__inner {
-                    background: $themeColor;
-                    color: #fff;
-                    border: none
-                }
-                .el-input .el-select__caret {
-                    color: #fff;
-                }
+            .el-select .el-input--suffix .el-input__inner {
+                background: #e3e4e6;
             }
             }
-            
         }
         }
         .user-menu {
         .user-menu {
             .user-menu-dropdown {
             .user-menu-dropdown {
-                color: #fff;
+                color: $colorWhite;
             }
             }
         }
         }
     }
     }
-    .page-container {
-        // background: #f2f2f2;
-        .page-sidebar-wrapper {
-            // color: azure;
-            background: #fff;
-            // .el-menu {
-            //     background: #364150;
-            // }
+
+    #page-container {
+        background: #f2f2f2;
+
+        #page-sidebar-wrapper {
+            color: azure;
+            background-color: #364150;
+            .sidebar-menu.el-menu {
+                background: #364150;
+
+                .sidebar-menu-submenu.el-submenu {
+                    &.is-active {
+                        .el-submenu__title {
+                            background: #36c6d3 !important;
+                            color: $colorWhite !important;
+                        }
+                    }
+                    .el-submenu__title {
+                        &:hover {
+                            background: #000;
+                        }
+                    }
+                }
+                .sidebar-menu-item.el-menu-item {
+                    &:hover {
+                        background: #000;
+                    }
+                    &.is-active {
+                        background: #36c6d3 !important;
+                        color: $colorWhite !important;
+                    }
+                }
+            }
         }
         }
         .page-content-wrapper {
         .page-content-wrapper {
             .page-content {
             .page-content {
                 .query-form {
                 .query-form {
                     border: 1px solid #dfe6ec;
                     border: 1px solid #dfe6ec;
-                    background-color: #fff;
+                    background-color: $colorWhite;
                 }
                 }
                 .data-table {
                 .data-table {
                     .el-table__header-wrapper {
                     .el-table__header-wrapper {
                         .el-table__header {
                         .el-table__header {
                             thead tr th {
                             thead tr th {
                                 background-color: #d9d9d9;
                                 background-color: #d9d9d9;
-                                // color: #000;
+                                color: #000;
                             }
                             }
                         }
                         }
                     }
                     }
@@ -63,7 +81,24 @@ $themeColor: #5BA7FF;
             }
             }
         }
         }
     }
     }
+
     .page-footer {
     .page-footer {
         background: #28303b;
         background: #28303b;
     }
     }
-}
+}
+
+.el-menu--vertical {
+    .el-menu.el-menu--popup.el-menu--popup-right-start {
+        .el-menu-item.sidebar-menu-item.is-active {
+            background: #36c6d3 !important;
+            color: $colorWhite !important;
+        }
+    }
+}
+
+.sidebar-menu-item.el-menu-item,
+.sidebar-menu-submenu.el-submenu .el-submenu__title {
+    i {
+        color: $colorWhite;
+    }
+}

+ 0 - 14
src/utils/basicutils.js

@@ -1,4 +1,3 @@
-import store from '@/store';
 function deepCopy(source) {
 function deepCopy(source) {
     if (!source) {
     if (!source) {
         return null
         return null
@@ -85,18 +84,5 @@ export default {
                 }
                 }
             }
             }
         }
         }
-    },
-    /**
-     * 判断该用户的权限是否具有某些权限
-     * @param {*}  promise 字符串
-     * @return ture | fasle
-     */
-    hasPermission: function(promise) {
-        let permissions = store.getters['layout/permissions']
-        if(permissions[promise]) {
-            return true;
-        } else {
-            return false
-        }
     }
     }
 }
 }

src/utils/storage.js → src/framework/utils/storage.js


+ 3 - 7
src/main.js

@@ -8,15 +8,11 @@ import store from './store'
 import ElementUI from 'element-ui'
 import ElementUI from 'element-ui'
 import 'element-ui/lib/theme-chalk/index.css'
 import 'element-ui/lib/theme-chalk/index.css'
 import './framework/style/awesome.less'
 import './framework/style/awesome.less'
-
-import './assets/scss/reset.scss'
-
-Vue.use(ElementUI, { size: "mini", zIndex: 1000 })
+Vue.use(ElementUI, { size: "small", zIndex: 1000 })
 
 
 import './framework/style/layout.scss'
 import './framework/style/layout.scss'
-import './utils/scan/directive' //自定义指令
 
 
-import componentsPlugin from '@/plugins/components'
+import componentsPlugin from '@/framework/plugins/components'
 Vue.use(componentsPlugin)
 Vue.use(componentsPlugin)
 
 
 Vue.config.productionTip = false
 Vue.config.productionTip = false
@@ -28,4 +24,4 @@ new Vue({
     store,
     store,
     components: { App },
     components: { App },
     template: '<App/>'
     template: '<App/>'
-})
+})

+ 0 - 17
src/router/demo.js

@@ -1,17 +0,0 @@
-import LayoutMain from '@/framework/layout/Main'
-
-import TablePageDemo from '@/views/demo/TablePageDemo'
-import FormPageDemo from '@/views/demo/FormPageDemo'
-
-export default [
-  {
-    path: '/demo',
-    name: 'LayoutMain',
-    component: LayoutMain,
-    children: [
-        { path: '', name: '', component: TablePageDemo },
-      { path: 'table', name: 'TablePageDemo', component: TablePageDemo },
-      { path: 'form', name: 'FormPageDemo', component: FormPageDemo }
-    ]
-  }
-]

+ 7 - 7
src/router/index.js

@@ -1,19 +1,19 @@
 import Vue from 'vue'
 import Vue from 'vue'
 import Router from 'vue-router'
 import Router from 'vue-router'
-import authutils from '@/utils/authutils'
-import demoRoute from './demo'
-import sagacloudRoute from './sagacloud'
+import frameworkApi from '@/api/framework'
+import demoRoute from '@/demo/demo-routes'
+import systemRoute from './system'
 Vue.use(Router)
 Vue.use(Router)
 
 
 let routes = []
 let routes = []
 routes = routes.concat(demoRoute)
 routes = routes.concat(demoRoute)
-routes = routes.concat(sagacloudRoute)
+routes = routes.concat(systemRoute)
 
 
 const router = new Router({
 const router = new Router({
-  mode: 'history',
-  routes: routes
+    mode: 'history',
+    routes: routes
 })
 })
 
 
-router.beforeEach(authutils.routerBeforeEach)
+router.beforeEach(frameworkApi.routerBeforeEach)
 
 
 export default router
 export default router

+ 11 - 7
src/router/sagacloud.js

@@ -1,7 +1,10 @@
 import LayoutMain from '@/framework/layout/Main'
 import LayoutMain from '@/framework/layout/Main'
 
 
-import Auth from '@/views/system/auth'
+import Login from '@/framework/layout/Login'
 import Dasboard from '@/views/dasboard'
 import Dasboard from '@/views/dasboard'
+
+import UserList from '@/views/system/user/UserList'
+import RoleList from '@/views/system/role/RoleList'
 import ChangePwd from '@/views/system/pwd/ChangePwd'
 import ChangePwd from '@/views/system/pwd/ChangePwd'
 
 
 /** 报警设置 */
 /** 报警设置 */
@@ -40,15 +43,16 @@ import facilityLedger from '@/views/ledger/facility'
 import propertyLedger from '@/views/ledger/property'
 import propertyLedger from '@/views/ledger/property'
 
 
 export default [
 export default [
-    { path: '/auth', name: 'Auth', component: Auth },
-    // 系统相关
+    { path: '/', name: '', component: LayoutMain },
+    { path: '/login', name: 'Login', component: Login },
     {
     {
-        path: '/',
+        path: '/system',
         name: 'LayoutMain',
         name: 'LayoutMain',
         component: LayoutMain,
         component: LayoutMain,
         children: [
         children: [
-            { path: '', name: 'Dasboard', component: Dasboard },
-            { path: '/system/changepwd', name: 'ChangePwd', component: ChangePwd }
+            { path: 'users', name: 'UserList', component: UserList },
+            { path: 'roles', name: 'RoleList', component: RoleList },
+            { path: 'changepwd', name: 'ChangePwd', component: ChangePwd }
         ]
         ]
     },
     },
     // 报警设置
     // 报警设置
@@ -183,4 +187,4 @@ export default [
             { path: 'revit', name: 'Dasboard', component: Dasboard }
             { path: 'revit', name: 'Dasboard', component: Dasboard }
         ]
         ]
     },
     },
-]
+]

+ 4 - 10
src/store/index.js

@@ -1,12 +1,9 @@
 import Vue from 'vue'
 import Vue from 'vue'
 import Vuex from 'vuex'
 import Vuex from 'vuex'
-import storage from '@/utils/storage'
+import storage from '@/framework/utils/storage'
 import layout from '@/framework/layout/layout-store'
 import layout from '@/framework/layout/layout-store'
-import project from "./modules/project"
-import peojMess from "./modules/proMess"
-import alarm from './modules/alarm'
 Vue.use(Vuex)
 Vue.use(Vuex)
-console.log(project, 'project')
+
 const KEY_LAST_ROUTE = 'last_route'
 const KEY_LAST_ROUTE = 'last_route'
 
 
 export default new Vuex.Store({
 export default new Vuex.Store({
@@ -37,9 +34,6 @@ export default new Vuex.Store({
     },
     },
     actions: {},
     actions: {},
     modules: {
     modules: {
-        layout,
-        project,
-        peojMess,
-        alarm
+        layout
     }
     }
-})
+})

+ 0 - 28
src/store/modules/alarm.js

@@ -1,28 +0,0 @@
-const alarm = {
-    namespaced: true,
-  state: {
-        index: 0, //刷新数据的index 递增刷新
-        spaceNameObj: null, //对象空间的名称字典
-        spaceCodeObj: null //对象类空间字典对象
-  },
-  getters: {
-      index: state => state.index,
-        spaceNameObj: state => state.spaceNameObj,
-        spaceCodeObj: state => state.spaceCodeObj
-  },
-  mutations: {
-    //   刷新index
-      ADD_INDEX(state) {
-        state.index = state.index + 1 ;
-      },
-    //   空间名称dict
-      SPACE_NAME_OBJ(state, spaceNameObj ){
-          state.spaceNameObj = spaceNameObj
-      },
-    //   空间code值dict
-        SPACE_CODE_OBJ(state, spaceCodeObj) {
-            state.spaceCodeObj = spaceCodeObj
-        }
-  }
-}
-export default alarm;

+ 0 - 29
src/store/modules/proMess.js

@@ -1,29 +0,0 @@
-const project_mess = {
-    namespaced: true,
-    state: {
-        projectId: "Pj4201050001", //项目id
-        secret: "saga123456", //数据源id
-        userId: "test", //数据源类型
-    },
-    mutations: {
-        set_project(state, val) {
-            state.projectId = val
-        },
-        set_secret(state, val) {
-            state.secret = val
-        },
-        set_userId(state, val) {
-            state.userId = val
-        }
-    },
-    actions: {
-
-    },
-    getters: {
-        projectId: state => state.projectId,
-        userId: state => state.userId,
-        secret: state => state.secret
-    }
-}
-
-export default project_mess

+ 0 - 42
src/store/modules/project.js

@@ -1,42 +0,0 @@
-const project_mess = {
-    namespaced: true,
-    state: {
-        projectId: "", //项目id
-        datasourceId: "4", //数据源id
-        protocolType: "amqp", //数据源类型
-        dataName: ""
-    },
-    mutations: {
-        set_project(state, val) {
-            state.projectId = val
-        },
-        set_datasource(state, val) {
-            state.datasourceId = val
-        },
-        set_protocol_type(state, val) {
-            state.protocolType = val
-        },
-        set_datasource_name(state, val) {
-            state.dataName = val
-        }
-    },
-    actions: {
-
-    },
-    getters: {
-        projectId: state => state.projectId,
-        datasourceId: state => state.datasourceId,
-        protocolType: state => state.protocolType,
-        dataName: state => state.dataName
-    }
-}
-
-let projectId = localStorage.getItem('projectId')
-if (!projectId) {
-    localStorage.setItem('projectId', '1234567890')
-    project_mess.state.projectId = '1234567890'
-} else {
-    project_mess.state.projectId = projectId
-}
-
-export default project_mess

+ 42 - 38
src/utils/authutils.js

@@ -36,10 +36,10 @@ export default {
      * @param {*} next
      * @param {*} next
      */
      */
     routerBeforeEach: async function(to, from, next) {
     routerBeforeEach: async function(to, from, next) {
-        // console.log('router before ', to)
-        if (to.path == '/auth') {
+        console.log('router before ', to)
+        if (to.path == '/auth' || to.path == '/nouser') {
             next()
             next()
-        } else {           
+        } else {
             // let userInfo = store.getters['layout/userInfo']
             // let userInfo = store.getters['layout/userInfo']
             // if (!userInfo) {
             // if (!userInfo) {
             //     // 本地是未登录状态, 保存目标页面地址, 去登录
             //     // 本地是未登录状态, 保存目标页面地址, 去登录
@@ -47,46 +47,50 @@ export default {
             //     store.commit('setLastRoute', lastRoute)
             //     store.commit('setLastRoute', lastRoute)
             //     toLogin()
             //     toLogin()
             // } else {
             // } else {
+            //     if (to.meta.breadcrumbs) {
+            //         store.dispatch('setBreadcrumb', to.meta.breadcrumbs)
+            //     }
             //     next()
             //     next()
             // }
             // }
-            next()
-            return true
+            // return true
+
+            next();
         }
         }
     },
     },
 
 
-    // routerBeforeEach2: async function(to, from, next) {
-    //     // console.log('router before ', to)
-    //     if (to.path == '/login') {
-    //         next()
-    //         return false
-    //     }
-    //     let userInfo = store.getters['layout/userInfo']
-    //     // console.log('user info ', userInfo)
-    //     if (!userInfo) {
-    //         // 本地是未登录状态, 检查是否有sso令牌
-    //         var token = httputils.getCookie('sagacloud-auth-token')
-    //         // console.log('sso token ', token)
-    //         if (!token) {
-    //             // 没有sso令牌, 跳转登录页面
-    //             toLogin()
-    //             return false
-    //         } else {
-    //             // 有sso令牌, 去服务端校验令牌并获取用户信息
-    //             // next({ path: to.path, params: to.params, query: to.query })
-    //             store.dispatch('layout/loadUserInfo').then(resp => {
-    //                 // console.log('store dispatch result ', resp)
-    //                 if (resp.result == 'success') {
-    //                     next({ path: to.path, params: to.params, query: to.query })
-    //                 } else {
-    //                     toLogin()
-    //                 }
-    //             })
-    //         }
-    //     } else {
-    //         next()
-    //     }
-    //     return true
-    // },
+    routerBeforeEach2: async function(to, from, next) {
+        console.log('router before ', to)
+        if (to.path == '/login') {
+            next()
+            return false
+        }
+        let userInfo = store.getters['layout/userInfo']
+        console.log('user info ', userInfo)
+        if (!userInfo) {
+            // 本地是未登录状态, 检查是否有sso令牌
+            var token = httputils.getCookie('sagacloud-auth-token')
+            console.log('sso token ', token)
+            if (!token) {
+                // 没有sso令牌, 跳转登录页面
+                toLogin()
+                return false
+            } else {
+                // 有sso令牌, 去服务端校验令牌并获取用户信息
+                // next({ path: to.path, params: to.params, query: to.query })
+                store.dispatch('layout/loadUserInfo').then(resp => {
+                    console.log('store dispatch result ', resp)
+                    if (resp.result == 'success') {
+                        next({ path: to.path, params: to.params, query: to.query })
+                    } else {
+                        toLogin()
+                    }
+                })
+            }
+        } else {
+            next()
+        }
+        return true
+    },
 
 
     getMenus(permissions) {
     getMenus(permissions) {
         let result = []
         let result = []

+ 0 - 40
src/views/system/auth/index.vue

@@ -1,40 +0,0 @@
-<template>
-    <div>
-        <h4>请稍候...</h4>
-    </div>
-</template>
-<script>
-import { mapGetters, mapMutations } from 'vuex'
-import adminapi from '@/api/system/admin'
-import authutils from '@/utils/authutils'
-export default {
-    name: 'index',
-    props: [],
-    data() {
-        return {}
-    },
-    created() {
-        // console.log('--------------------- index created')
-        // console.log(this.$route.query)
-        let token = this.$route.query.token
-        this.$store.commit('setSsoToken', token)   
-             
-        this.$store.dispatch('layout/loadUserInfo').then(resp => {
-            console.log('store dispatch result ', resp)
-            if (resp.result == 'success') {
-                let lastRoute = this.$store.getters['lastRoute']
-                console.log('last route ', lastRoute)
-                if (lastRoute) {
-                    this.$router.replace(lastRoute)
-                } else {
-                    this.$router.replace('/')
-                }
-            } else {
-                authutils.toLoginPage()
-            }
-        })
-    },
-    mounted() {},
-    components: {}
-}
-</script>

+ 0 - 3
src/views/system/pwd/ChangePwd.vue

@@ -93,9 +93,6 @@ export default {
         resetForm(formName) {
         resetForm(formName) {
             this.$refs[formName].resetFields()
             this.$refs[formName].resetFields()
         }
         }
-    },
-    created() {
-        this.$store.dispatch('setBreadcrumb', [{ label: '修改密码' }])
     }
     }
 }
 }
 </script>
 </script>

+ 78 - 0
src/views/system/role/RoleEdit.vue

@@ -0,0 +1,78 @@
+<template>
+    <el-dialog title='创建角色' :visible.sync='dialogVisible'>
+        <el-form ref='form' :model='formValue' :rules='roleRules' label-width='100px'>
+            <el-form-item label='角色名' prop='name'>
+                <el-input v-model.trim='formValue.name'></el-input>
+            </el-form-item>
+            <el-form-item label='备注' prop='remark'>
+                <el-input v-model.trim='formValue.remark'></el-input>
+            </el-form-item>
+        </el-form>
+        <div class='btn-box'>
+            <el-button type='primary' size='mini' @click='save'>创建角色</el-button>
+        </div>
+    </el-dialog>
+</template>
+<script>
+import roleapi from '@/api/system/role'
+export default {
+    name: 'RoleEdit',
+    data() {
+        return {
+            title: '创建角色',
+            dialogVisible: false,
+            type: null,
+            formValue: { id: null, name: null, remark: null },
+            roleRules: {
+                name: [{ required: true, message: '请输入角色名称', trigger: 'blur' }]
+            }
+        }
+    },
+    methods: {
+        show(row) {
+            console.log(row)
+            this.dialogVisible = true
+            if (row) {
+                this.type = 'update'
+                this.title = '编辑角色'
+                this.formValue.id = row.id
+                this.formValue.name = row.name
+                this.formValue.remark = row.remark
+            } else {
+                this.type = 'create'
+                this.title = '创建角色'
+                this.formValue.id = null
+                this.formValue.name = null
+                this.formValue.remark = null
+            }
+        },
+        save() {
+            this.$refs['form'].validate(valid => {
+                if (valid) {
+                    console.log(this.formValue)
+                    if (this.type == 'create') {
+                        roleapi.create(this.formValue).then(resp => {
+                            console.log('create role ', resp)
+                            this.$message.success(this.title + '成功')
+                            this.$emit('saved')
+                            this.dialogVisible = false
+                        })
+                    } else {
+                        roleapi.update(this.formValue).then(resp => {
+                            console.log('update role ', resp)
+                            this.$message.success(this.title + '成功')
+                            this.$emit('saved')
+                            this.dialogVisible = false
+                        })
+                    }
+                }
+            })
+        }
+    }
+}
+</script>
+<style lang="less" scoped>
+.btn-box {
+    text-align: center;
+}
+</style>

+ 87 - 0
src/views/system/role/RoleList.vue

@@ -0,0 +1,87 @@
+<template>
+    <table-page-template>
+        <el-form :inline='true' slot='form' size='mini'>
+            <el-form-item label='用户'>
+                <el-input class='input' v-model.trim='searchValue' placeholder='请输入name进行查询' clearable></el-input>
+            </el-form-item>
+            <el-form-item>
+                <el-button type='primary' @click='query'>查询</el-button>
+                <el-button type='primary' @click='editRole(null)'>创建角色</el-button>
+            </el-form-item>
+        </el-form>
+        <el-table :data='roles' border stripe style='width: 100%' slot='table'>
+            <el-table-column prop='id' label='ID' width='50'></el-table-column>
+            <el-table-column prop='name' label='Name'></el-table-column>
+            <el-table-column prop='remark' label='备注'></el-table-column>
+            <el-table-column label='操作' width='250'>
+                <template slot-scope='scope'>
+                    <el-button @click='editRole(scope.row)' type='primary' size='small'>编辑</el-button>
+                    <el-button @click='editAuth(scope.row)' type='primary' size='small'>配置权限</el-button>
+                    <el-button @click='deleteRole(scope.row)' type='danger' size='small'>删除</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+        <div slot='dialog'>
+            <role-edit ref='roleEdit' @saved='query'></role-edit>
+            <role-manage ref='roleManage'></role-manage>
+        </div>
+    </table-page-template>
+</template>
+<script>
+import roleapi from '@/api/system/role'
+import RoleEdit from './RoleEdit'
+import RoleManage from './RoleManage'
+export default {
+    name: 'RoleList',
+    data() {
+        return {
+            roles: [],
+            searchValue: ''
+        }
+    },
+    methods: {
+        query() {
+            let criteria = {}
+            if (this.searchValue) {
+                criteria.name = { $like: this.searchValue + '%' }
+            }
+            roleapi.query({ criteria }).then(resp => {
+                this.roles = resp.content
+            })
+        },
+        editRole(row) {
+            this.$refs['roleEdit'].show(row)
+        },
+        editAuth(row) {
+            this.$refs['roleManage'].show()
+        },
+        deleteRole(row) {
+            let opt = {
+                confirmButtonText: '确定',
+                cancelButtonText: '取消',
+                type: 'warning'
+            }
+            this.$confirm('此操作将永久删除, 是否继续?', '提示', opt)
+                .then(() => {
+                    let params = { id: row.id }
+                    roleapi.delete(params).then(res => {
+                        if (res.result == 'success') {
+                            this.$message.success('删除成功')
+                            this.query()
+                        } else {
+                            this.$message.error('删除失败: ' + res.message)
+                        }
+                    })
+                })
+                .catch(() => {})
+        }
+    },
+    created() {
+        this.query()
+    },
+    components: {
+        RoleEdit,
+        RoleManage
+    }
+}
+</script>

+ 170 - 0
src/views/system/role/RoleManage.vue

@@ -0,0 +1,170 @@
+<template>
+    <el-dialog title='权限管理' :visible.sync='dialogVisible' top='5vh' width='60%'>
+        <div class='box'>
+            <div class='custom-tree-container'>
+                <div class='block'>
+                    <el-tree
+                        ref='tree'
+                        :data='data'
+                        node-key='id'
+                        default-expand-all
+                        show-checkbox
+                        :props='treeProps'
+                        :expand-on-click-node='false'
+                        :default-checked-keys='checkedBoxArr'
+                        @check='getCurrentKey'
+                    >
+                        <span class='custom-tree-node' slot-scope='{ node, data }'>
+                            <span>{{ node.label }}</span>
+                            <span v-if='data.level == "second"'>
+                                <el-checkbox
+                                    v-for='(opt,index) in data.opts'
+                                    :key='index'
+                                    v-model='opt.checked'
+                                    @change='changeCheckBox(node, data)'
+                                >{{opt.name}}</el-checkbox>
+                            </span>
+                        </span>
+                    </el-tree>
+                </div>
+            </div>
+            <div class='btn-box'>
+                <el-button type='primary' @click='save'>保 存</el-button>
+            </div>
+        </div>
+    </el-dialog>
+</template>
+
+<script>
+import menus from '@/data/menus'
+import utils from './eleTreeUtils'
+export default {
+    name: 'ele-tree',
+    data() {
+        return {
+            dialogVisible: false,
+            treeProps: {
+                label: 'name'
+            },
+            permissions: [],
+            data: [],
+            checkedBoxArr: [] //被选中的数组
+        }
+    },
+    methods: {
+        show() {
+            this.dialogVisible = true
+        },
+        changeCheckBox(node, data) {
+            utils.changeChecked(this.data)
+            let flag = true
+            if (data.opts) {
+                data.opts.forEach(opt => {
+                    if (!opt.checked) {
+                        flag = false
+                    }
+                })
+            }
+            if (flag) {
+                this.$refs['tree'].setChecked(data.id, true)
+            } else {
+                this.$refs['tree'].setChecked(data.id, false)
+            }
+        },
+        //tree发生变化
+        getCurrentKey(node, keys) {
+            let checkedId = node.id
+            //id-dict
+            let checkedObjIds = {}
+            keys.checkedKeys.forEach(id => {
+                checkedObjIds[id] = true
+            })
+            //选中的时候
+            keys.checkedNodes.forEach(node => {
+                if (node.opts) {
+                    node.opts.forEach(opt => {
+                        opt.checked = true
+                    })
+                }
+            })
+            //取消选中的时候
+            if (checkedObjIds[checkedId]) {
+            } else {
+                //点击第二级
+                if (node.opts) {
+                    node.opts.forEach(ele => {
+                        ele.checked = false
+                    })
+                }
+                //点击第一级
+                if (node.children) {
+                    node.children.forEach(second => {
+                        if (second.opts) {
+                            second.opts.forEach(opt => {
+                                opt.checked = false
+                            })
+                        }
+                    })
+                }
+            }
+        },
+        save() {
+            let arr = []
+            this.data.forEach(first => {
+                if (first.children) {
+                    first.children.forEach(second => {
+                        if (second.opts) {
+                            second.opts.forEach(opt => {
+                                if (opt.checked) {
+                                    arr.push(opt.permission)
+                                }
+                            })
+                        }
+                    })
+                }
+            })
+            console.log(arr)
+        },
+        isCheckBasic() {
+            utils.changeChecked(this.data)
+        },
+        init() {
+            console.log('menus = ', menus)
+            let _menus = menus.demoMenus
+            _menus = _menus.concat(menus.menus)
+            let arr = utils.initCheckboxList(_menus, this.permissions)
+            //获取默认选中
+            this.checkedBoxArr = utils.getCheckedNodeArr(arr)
+            this.data = arr
+        }
+    },
+    created() {
+        this.init()
+    }
+}
+</script>
+
+<style>
+.custom-tree-node {
+    flex: 1;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    font-size: 14px;
+    padding-right: 8px;
+}
+.el-tree-node__content {
+    border-bottom: 1px solid #e6e6e6;
+}
+</style>
+<style scoped lang='less'>
+.box {
+    max-height: 500px;
+    overflow: hidden;
+    .btn-box {
+        margin-top: 10px;
+        text-align: center;
+    }
+}
+</style>
+

+ 132 - 0
src/views/system/role/eleTreeUtils.js

@@ -0,0 +1,132 @@
+//初始化checkBox--list
+const utils = {
+    initCheckboxList(menus, permissions) {
+        var permissObj = {}
+        permissions.forEach(permission => {
+            permissObj[permission] = true
+        })
+        let arr = []
+        var id = 1;
+        menus.forEach(first => {
+            let firstObj = {id: id++, name: first.name, level: 'first' }
+            if (first.children) {
+                firstObj.children = []
+                first.children.forEach(second => {
+                    let secondObj = { id: id++, name: second.name, level: 'second' }
+                    if (second.opts) {
+                        secondObj.opts = []
+                        second.opts.forEach(third => {
+                            let flag = this.isChecked(third, permissObj)
+                            let thirdObj = {}
+                            if (flag) {
+                                thirdObj = { id: id++, name: third.name, checked: true, permission: third.permission, basic: third.basic }
+                            } else {
+                                thirdObj = { id: id++, name: third.name, checked: false, permission: third.permission, basic: third.basic }
+                            }
+                            secondObj.opts.push(thirdObj)
+                        })
+                    }
+                    firstObj.children.push(secondObj)
+                })
+            }
+            arr.push(firstObj)
+        })
+        return this.isBasic(arr, permissObj)
+    },
+    // 判断当前是否在权限里
+    isChecked(opt, permissObj) {
+        if (permissObj[opt.permission]) {
+            return true
+        } else {
+            return false
+        }
+    },
+    //判断是否为basic,[basic同级 假如有checked的则basic为true]
+    isBasic(arr, permissObj) {
+        arr.forEach(first => {
+            if (first.children) {
+                first.children.forEach(second => {
+                    if (second.children) {
+                        second.children.forEach(opts => {
+                            if (opts.basic) {
+                                // 1。是basic
+                                if (permissObj[opts.value]) {
+                                    //2.有权限
+                                } else {
+                                    let flag = this.isBasicOther(second.children)
+                                    if (flag) {
+                                        opts.checked = true
+                                    }
+                                }
+                            }
+                        })
+                    }
+                })
+            }
+        })
+        return arr
+    },
+    //判断和basic同级的是否有被选中的
+    isBasicOther(arr) {
+        let flag = false
+        arr.forEach(opt => {
+            if (!opt.basic) {
+                if (opt.checked) {
+                    flag = true
+                }
+            }
+        })
+        return flag
+    },
+    /********************************************************************************** */
+    //当点击的时候,判断时候为basic,如果不是,查看basic是否选中
+    changeChecked(data) {
+        data.forEach(first => {
+            if (first.children) {
+                first.children.forEach(second => {
+                    if (second.opts) {
+                        second.opts.forEach(opt => {
+                            // console.log(opt)
+                            if (opt.basic) {
+                                //基本权限
+                            } else {
+                                if (opt.checked) {
+                                    this.checkedBasic(second.opts)
+                                }
+                            }
+                        })
+                    }
+                })
+            }
+        })
+    },
+    checkedBasic(arr) {
+        arr.forEach(item => {
+            if(item.basic) {
+                item.checked  = true
+            }
+        })
+    },
+    getCheckedNodeArr(arr) {
+        let checkedIdArr = [];
+        arr.forEach(first => {
+            if(first.children) {
+                first.children.forEach(second => {
+                    if(second.opts) {
+                        let flag = true
+                        second.opts.forEach(opt => {
+                            if(!opt.checked){
+                                flag = false
+                            }
+                        })
+                        if(flag) {
+                            checkedIdArr.push(second.id)
+                        }
+                    }
+                })
+            }
+        })
+        return checkedIdArr
+    }
+}
+export default utils

+ 100 - 0
src/views/system/user/UserAdd.vue

@@ -0,0 +1,100 @@
+<template>
+    <el-dialog :title='title' :visible.sync='dialogFormVisible' @close='close'>
+        <el-form :model='form' :rules='newUserRules' ref='loginForm'>
+            <el-form-item label='用户名' :label-width='formLabelWidth'>
+                <el-input v-model='form.name' auto-complete='off'></el-input>
+            </el-form-item>
+            <el-form-item label='备注' :label-width='formLabelWidth'>
+                <el-input v-model='form.remark' auto-complete='off'></el-input>
+            </el-form-item>
+            <el-form-item label='角色' :label-width='formLabelWidth'>
+                <el-checkbox-group v-model='form.roleIds'>
+                    <el-checkbox v-for='role in roles' :label='role.id' :key='role.id'>{{role.name}}</el-checkbox>
+                </el-checkbox-group>
+            </el-form-item>
+        </el-form>
+        <div slot='footer' class='dialog-footer'>
+            <el-button @click='close'>取消</el-button>
+            <el-button type='primary' @click='save()'>保存</el-button>
+        </div>
+    </el-dialog>
+</template>
+<script>
+import userapi from '@/api/system/user'
+import roleapi from '@/api/system/role'
+export default {
+    name: 'UserAdd',
+    data() {
+        return {
+            dialogFormVisible: false,
+            formLabelWidth: '120px',
+            roles: null,
+            title: null,
+            form: {
+                id: null,
+                name: null,
+                remark: null,
+                roleIds: []
+            },
+            newUserRules: {
+                username: [{ required: true, trigger: 'blur', validator: this.validateUsername }]
+            }
+        }
+    },
+    methods: {
+        open(data) {
+            let vm = this
+            vm.dialogFormVisible = true
+            if (!vm.roles) {
+                roleapi.query({ criteria: {} }).then(resp => (vm.roles = resp.content))
+            }
+            if (data) {
+                this.title = '编辑用户'
+                vm.form.id = data.id
+                vm.form.name = data.name
+                vm.form.remark = data.remark
+                vm.form.roleIds = []
+                if (data.roles) {
+                    data.roles.forEach(item => vm.form.roleIds.push(item.id))
+                }
+            } else {
+                this.title = '创建用户'
+            }
+        },
+        save() {
+            let vm = this
+            let url
+            if (vm.form.id) {
+                userapi.update(vm.form).then(this.saveResult)
+            } else {
+                userapi.create(vm.form).then(this.saveResult)
+            }
+        },
+        saveResult(resp) {
+            if (resp.result == 'success') {
+                this.$message.success(this.title + '成功')
+                this.dialogFormVisible = false
+                this.$emit('confirm')
+            } else {
+                this.$message.error(this.title + '失败')
+            }
+        },
+        validateUsername() {
+            return true
+        },
+        close() {
+            let vm = this
+            vm.dialogFormVisible = false
+            if (vm.form.id) {
+                vm.form.id = null
+                vm.form.name = null
+                vm.form.remark = null
+                vm.form.roleIds = []
+            }
+            vm.$emit('cancel')
+        }
+    }
+}
+</script>
+<style lang="css" scoped>
+</style>

+ 82 - 0
src/views/system/user/UserList.vue

@@ -0,0 +1,82 @@
+<template>
+    <table-page-template>
+        <el-form :inline='true' :model='queryData' slot='form' size='mini'>
+            <el-form-item label='用户'>
+                <el-input v-model.trim='queryData.username'></el-input>
+            </el-form-item>
+            <el-form-item>
+                <el-button type='primary' @click='query'>查询</el-button>
+                <el-button type='primary' @click='openAdd(null)'>新增</el-button>
+            </el-form-item>
+        </el-form>
+        <el-table :data='pageData.users' border stripe slot='table'>
+            <el-table-column prop='id' label='ID'></el-table-column>
+            <el-table-column prop='name' label='Name'></el-table-column>
+            <el-table-column prop='remark' label='Remark'></el-table-column>
+            <el-table-column prop='status' label='Status'></el-table-column>
+            <el-table-column label='操作' width='150'>
+                <template slot-scope='{row}'>
+                    <el-button type='primary' size='mini' @click='openAdd(row)'>编辑</el-button>
+                    <el-button type='danger' size='mini' @click='deleteBtnClicked(row)'>删除</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+        <base-pagination :total='pageData.total' @pageChanged='pageChanged' slot='pagination'></base-pagination>
+        <user-add ref='addUser' @confirm='getData' slot='dialog'></user-add>
+    </table-page-template>
+</template>
+<script>
+import userapi from '@/api/system/user'
+import UserAdd from './UserAdd'
+export default {
+    name: 'UserList',
+    data() {
+        return {
+            queryData: {
+                username: null
+            },
+            pageData: {
+                page: 1,
+                size: 10,
+                total: 0,
+                users: []
+            }
+        }
+    },
+    methods: {
+        openAdd(user) {
+            this.$refs.addUser.open(user)
+        },
+        pageChanged(page, size) {
+            this.pageData.page = page
+            this.pageData.size = size
+            this.getData(page, size)
+        },
+        query() {
+            this.pageData.page = 1
+            this.pageData.size = 10
+            this.getData()
+        },
+        async getData() {
+            let vm = this
+            let username = this.queryData.username
+            let criteria = {}
+            if (username) {
+                criteria.name = username
+            }
+
+            let request = { page: vm.pageData.page, size: vm.pageData.size, criteria: criteria }
+            userapi.query(request).then(resp => {
+                vm.pageData.total = resp.count
+                vm.pageData.users = resp.content
+            })
+        }
+    },
+    created() {
+        this.query()
+    },
+    components: {
+        'user-add': UserAdd
+    }
+}
+</script>