From 32a6f62e6ded8a958fb295cc1bb8ffdd93803fa9 Mon Sep 17 00:00:00 2001 From: harsima Date: Thu, 16 Nov 2017 19:03:23 +0800 Subject: [PATCH] reset file --- .babelrc | 16 + .editorconfig | 13 + .eslintignore | 3 + .eslintrc.js | 38 ++ .gitignore | 6 + .postcssrc.js | 8 + README.md | 105 +++ build/build.js | 41 ++ build/check-versions.js | 48 ++ build/dev-client.js | 10 + build/dev-server.js | 105 +++ build/utils.js | 72 +++ build/vue-loader.conf.js | 25 + build/webpack.base.conf.js | 78 +++ build/webpack.dev.conf.js | 36 ++ build/webpack.prod.conf.js | 132 ++++ config/dev.env.js | 7 + config/index.js | 40 ++ config/prod.env.js | 4 + jsconfig.json | 5 + mock/echarts.js | 28 + mock/index.js | 13 + mock/login.js | 13 + mock/navlist.js | 118 ++++ package.json | 89 +++ src/components/customCom/global/install.js | 0 .../locale/signalGroup/dialogView.vue | 121 ++++ .../locale/signalGroup/signalGroup.vue | 94 +++ .../locale/signalGroup/signalItem.1.vue | 125 ++++ .../locale/signalGroup/signalItem.vue | 126 ++++ .../platformCom/hasPermission/index.js | 18 + src/components/platformCom/install.js | 29 + src/components/platformCom/pageNotes/index.js | 7 + src/components/platformCom/pageNotes/main.vue | 24 + .../platformCom/pageSearch/index.js | 7 + .../platformCom/pageSearch/main.vue | 22 + .../platformCom/pageSection/index.js | 7 + .../platformCom/pageSection/main.vue | 44 ++ src/components/platformCom/pageTable/index.js | 7 + src/components/platformCom/pageTable/main.vue | 85 +++ src/components/platformCom/pageTitle/index.js | 7 + src/components/platformCom/pageTitle/main.vue | 28 + .../platformCom/pageToolbar/index.js | 7 + .../platformCom/pageToolbar/main.vue | 32 + src/index.html | 15 + src/index.vue | 66 ++ src/lang/en.js | 4 + src/lang/zh-cn.js | 4 + src/main.js | 27 + src/page/components/assist/pageNotes.vue | 42 ++ src/page/components/function/pageTable.vue | 78 +++ src/page/components/function/permission.vue | 40 ++ src/page/components/index.vue | 34 + src/page/components/ui/pageSearch.vue | 42 ++ src/page/components/ui/pageSection.vue | 42 ++ src/page/components/ui/pageTitle.vue | 42 ++ src/page/components/ui/pageToolbar.vue | 45 ++ src/page/error/401.vue | 16 + src/page/error/403.vue | 16 + src/page/error/404.vue | 16 + src/page/error/500.vue | 16 + src/page/error/error.vue | 18 + src/page/example/charts/chart1.vue | 92 +++ src/page/example/charts/charts.vue | 42 ++ src/page/example/map/map.vue | 31 + src/page/example/map/map1.vue | 32 + src/page/example/table.vue | 177 +++++ src/page/form/form.vue | 14 + src/page/home/home.vue | 86 +++ src/page/i18n/i18n.vue | 202 ++++++ src/page/layout/Header.vue | 192 ++++++ src/page/layout/Sidenav.1.vue | 173 +++++ src/page/layout/Sidenav.vue | 180 ++++++ src/page/layout/layout.vue | 66 ++ src/page/layout/navItem.1.vue | 37 ++ src/page/layout/navItem.vue | 17 + src/page/login/login.vue | 228 +++++++ src/page/table/table.vue | 111 ++++ src/page/themeChange/themeChange.vue | 78 +++ src/resources/css/reset.scss | 118 ++++ src/resources/css/theme/default/default.scss | 34 + src/resources/css/theme/theme.scss | 10 + src/resources/images/layout-left.png | Bin 0 -> 2399 bytes src/resources/images/layout-top.png | Bin 0 -> 2043 bytes src/resources/images/logo.png | Bin 0 -> 3907 bytes src/resources/libs/element-variables.css | 605 ++++++++++++++++++ src/router/asyncRouter.js | 120 ++++ src/router/directAccess.js | 11 + src/router/index.js | 164 +++++ src/store/index.js | 13 + src/store/modules/index.js | 7 + src/store/modules/permission/index.js | 50 ++ src/store/modules/user/index.js | 117 ++++ src/store/mutations.js | 21 + src/store/state.js | 14 + src/util/Cookie.js | 41 ++ src/util/ajax.js | 46 ++ src/util/amap.js | 22 + src/util/echarts.theme.default.js | 496 ++++++++++++++ src/util/i18n.js | 41 ++ static/.gitkeep | 0 101 files changed, 6094 insertions(+) create mode 100644 .babelrc create mode 100644 .editorconfig create mode 100644 .eslintignore create mode 100644 .eslintrc.js create mode 100644 .gitignore create mode 100644 .postcssrc.js create mode 100644 README.md create mode 100644 build/build.js create mode 100644 build/check-versions.js create mode 100644 build/dev-client.js create mode 100644 build/dev-server.js create mode 100644 build/utils.js create mode 100644 build/vue-loader.conf.js create mode 100644 build/webpack.base.conf.js create mode 100644 build/webpack.dev.conf.js create mode 100644 build/webpack.prod.conf.js create mode 100644 config/dev.env.js create mode 100644 config/index.js create mode 100644 config/prod.env.js create mode 100644 jsconfig.json create mode 100644 mock/echarts.js create mode 100644 mock/index.js create mode 100644 mock/login.js create mode 100644 mock/navlist.js create mode 100644 package.json create mode 100644 src/components/customCom/global/install.js create mode 100644 src/components/customCom/locale/signalGroup/dialogView.vue create mode 100644 src/components/customCom/locale/signalGroup/signalGroup.vue create mode 100644 src/components/customCom/locale/signalGroup/signalItem.1.vue create mode 100644 src/components/customCom/locale/signalGroup/signalItem.vue create mode 100644 src/components/platformCom/hasPermission/index.js create mode 100644 src/components/platformCom/install.js create mode 100644 src/components/platformCom/pageNotes/index.js create mode 100644 src/components/platformCom/pageNotes/main.vue create mode 100644 src/components/platformCom/pageSearch/index.js create mode 100644 src/components/platformCom/pageSearch/main.vue create mode 100644 src/components/platformCom/pageSection/index.js create mode 100644 src/components/platformCom/pageSection/main.vue create mode 100644 src/components/platformCom/pageTable/index.js create mode 100644 src/components/platformCom/pageTable/main.vue create mode 100644 src/components/platformCom/pageTitle/index.js create mode 100644 src/components/platformCom/pageTitle/main.vue create mode 100644 src/components/platformCom/pageToolbar/index.js create mode 100644 src/components/platformCom/pageToolbar/main.vue create mode 100644 src/index.html create mode 100644 src/index.vue create mode 100644 src/lang/en.js create mode 100644 src/lang/zh-cn.js create mode 100644 src/main.js create mode 100644 src/page/components/assist/pageNotes.vue create mode 100644 src/page/components/function/pageTable.vue create mode 100644 src/page/components/function/permission.vue create mode 100644 src/page/components/index.vue create mode 100644 src/page/components/ui/pageSearch.vue create mode 100644 src/page/components/ui/pageSection.vue create mode 100644 src/page/components/ui/pageTitle.vue create mode 100644 src/page/components/ui/pageToolbar.vue create mode 100644 src/page/error/401.vue create mode 100644 src/page/error/403.vue create mode 100644 src/page/error/404.vue create mode 100644 src/page/error/500.vue create mode 100644 src/page/error/error.vue create mode 100644 src/page/example/charts/chart1.vue create mode 100644 src/page/example/charts/charts.vue create mode 100644 src/page/example/map/map.vue create mode 100644 src/page/example/map/map1.vue create mode 100644 src/page/example/table.vue create mode 100644 src/page/form/form.vue create mode 100644 src/page/home/home.vue create mode 100644 src/page/i18n/i18n.vue create mode 100644 src/page/layout/Header.vue create mode 100644 src/page/layout/Sidenav.1.vue create mode 100644 src/page/layout/Sidenav.vue create mode 100644 src/page/layout/layout.vue create mode 100644 src/page/layout/navItem.1.vue create mode 100644 src/page/layout/navItem.vue create mode 100644 src/page/login/login.vue create mode 100644 src/page/table/table.vue create mode 100644 src/page/themeChange/themeChange.vue create mode 100644 src/resources/css/reset.scss create mode 100644 src/resources/css/theme/default/default.scss create mode 100644 src/resources/css/theme/theme.scss create mode 100644 src/resources/images/layout-left.png create mode 100644 src/resources/images/layout-top.png create mode 100644 src/resources/images/logo.png create mode 100644 src/resources/libs/element-variables.css create mode 100644 src/router/asyncRouter.js create mode 100644 src/router/directAccess.js create mode 100644 src/router/index.js create mode 100644 src/store/index.js create mode 100644 src/store/modules/index.js create mode 100644 src/store/modules/permission/index.js create mode 100644 src/store/modules/user/index.js create mode 100644 src/store/mutations.js create mode 100644 src/store/state.js create mode 100644 src/util/Cookie.js create mode 100644 src/util/ajax.js create mode 100644 src/util/amap.js create mode 100644 src/util/echarts.theme.default.js create mode 100644 src/util/i18n.js create mode 100644 static/.gitkeep diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..148efbf --- /dev/null +++ b/.babelrc @@ -0,0 +1,16 @@ +{ + "presets": [ + ["env", { "modules": false }], + "stage-2" + ], + "plugins": [ + // "transform-runtime" + ], + "comments": false, + "env": { + "test": { + "presets": ["env", "stage-2"], + "plugins": [ "istanbul" ] + } + } +} diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..22dcb2d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +insert_final_newline = false +trim_trailing_whitespace = false diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..fde9f2c --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +build/*.js +config/*.js +src/assets \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..026eca3 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,38 @@ +module.exports = { + root: true, + parser: 'babel-eslint', //解析器,这里我们使用babel-eslint + parserOptions: { + sourceType: 'module' //类型为module,因为代码使用了使用了ECMAScript模块 + }, + env: { + browser: true, //预定义的全局变量,这里是浏览器环境\ + commonjs: true, + node: true, + es6: true + }, + // /~https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style + // extends: 'standard', //扩展,可以通过字符串或者一个数组来扩展规则 + // required to lint *.vue files + plugins: [ + 'html' //插件,此插件用于识别文件中的js代码,没有MIME类型标识没有script标签也可以识别到,因此拿来识别.vue文件中的js代码 + ], + // check if imports actually resolve + 'settings': { + 'import/resolver': { + 'webpack': { + 'config': 'build/webpack.base.conf.js' + } + } + }, + // add your custom rules here + 'rules': { + //这里写自定义规则 + "no-const-assign": "warn", + "no-this-before-super": "warn", + "no-undef": "warn", + "no-unreachable": "warn", + "no-unused-vars": "warn", + "constructor-super": "warn", + "valid-typeof": "warn" + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2598277 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.DS_Store +node_modules/ +dist/ +npm-debug.log* +BEFORE_USE.md +codeDesign/ \ No newline at end of file diff --git a/.postcssrc.js b/.postcssrc.js new file mode 100644 index 0000000..ea9a5ab --- /dev/null +++ b/.postcssrc.js @@ -0,0 +1,8 @@ +// /~https://github.com/michael-ciniawsky/postcss-load-config + +module.exports = { + "plugins": { + // to edit target browsers: use "browserlist" field in package.json + "autoprefixer": {} + } +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..6f0bfd3 --- /dev/null +++ b/README.md @@ -0,0 +1,105 @@ +# Vue + ElementUI 后台管理系统框架 + +>本框架为后台管理类系统解决方案,其中包含很多后台管理中的必备功能。当前版本仅供学习交流,框架中vue及webpack版本会随时更新,尽量采用平滑升级策略,修改部分全局或打包配置完成,如果更改过大,版本号将自动增加,并提供之前版本的release,所以如果注重稳定的话,请在生产环境中谨慎使用。 + +## **功能列表** +- 登录登出 +- 菜单异步加载 +- 页面详细权限控制 +- 多语言支持 +- 布局切换 +- 高德地图集成 +- Echarts集成 +- 错误页面 +- mock数据 +- 页面加载进度条 +- 级联选择示例 + +## **项目使用** +``` bash +# 安装项目依赖 +npm install + +# 开启本地服务,默认为localhost:9000 +npm run dev + +# 项目打包,构建生产环境 +npm run build + +# 打包过程中想查看具体报告则可以通过以下命令实现 +npm run build --report +``` + + +## **项目结构** +本项目的开发代码目录结构如下,在编码时请按照规则放置代码 + +``` bash +./root +├── ... +│ ├── mock/ // 模拟请求 +├── src +│ ├── components +│ │ ├── platformCom // 平台通用组件 +│ │ │ ├── ... +│ │ │ ├── install.js // 平台组件全局注册 +│ │ ├── customCom // 项目组件 +│ │ │ ├── global/ // 项目全局组件 +│ │ │ │ ├── ... +│ │ │ │ ├── install.js // 项目全局组件安装 +│ │ │ ├── locale/ // 项目局部组件 +│ ├── lang // 国际化文件 +│ │ ├── en.js +│ │ ├── zh-cn.js +│ │ ├── ... +│ ├── page // 项目页面 +│ │ ├── ... // 页面名称 +│ │ │ ├── *.vue // vue文件 +│ │ │ ├── ... +│ ├── resources // 静态资源 +│ │ ├── ... +│ ├── util // 通用工具 +│ │ ├── http.js // ajax全局设置 +│ │ ├── i18n.js // 国际化全局设置 +│ │ ├── amap.js // 高德地图注册 +│ │ ├── ... +│ ├── store // vuex状态管理 +│ │ ├── modules/ // vuex的modules +│ │ ├── state.js +│ │ ├── getter.js +│ │ ├── mutations.js +│ │ ├── actions.js +│ │ ├── store.js +│ ├── router +│ │ ├── asyncRouter.js // 异步路由表 +│ │ ├── directAccess.js // 直接访问路由表(预留) +│ │ ├── index.js // vue-router路由配置 +│ ├── index.html // 单文件入口渲染模板 +│ ├── index.vue // 首页vue +│ ├── main.js // webpack入口文件 +├── ... +``` + + + +## **更新计划** +- ~~修复 多语言在单文件组件中无法切换的BUG~~ +- ~~高德地图及echarts组件化~~ + + ~~当前加载方式属于一次性注册,可以进一步组件化。~~ +- 文件目录优化 + + 当前组件目录可能过于冗余,以后可能会进行合并。或者增加分支,把真正的源放到另外的分支中,本分支只面向大众一般情况。 +- 更好的组件加载方式 + + 当前异步组件加载方式看着很别扭,同时会有过多的script和style标签,需要后续优化。 +- 完善打包策略 + + 当前打包策略并不完善。理想中的策略应该是所有第三方组件打包在一起,业务与首页分离,即最后应该是vendor(lib)、home/index、page(相同业务或相同菜单在一起)。 +- 界面UI重新定制,形成完整的主题。 +- 完全的优雅的主题切换方式 + + 当前其实并没有完成主题切换方式,只是更改了布局。当前CSS写法方面在面对主题切换时遇到很大的问题,初步想法是不在 `.vue` 文件中编写css,把所有的css提到单独文件中,以便管理。主题切换则采用加载固定CSS文件的方式。这里会继续写一个博客。 + +- ElementUI v3.0更新,更新前会发布release版本 +- 消息推送 \ No newline at end of file diff --git a/build/build.js b/build/build.js new file mode 100644 index 0000000..4768b22 --- /dev/null +++ b/build/build.js @@ -0,0 +1,41 @@ +'use strict' +require('./check-versions')() + +process.env.NODE_ENV = 'production' + +const ora = require('ora') +const rm = require('rimraf') +const path = require('path') +const chalk = require('chalk') +const webpack = require('webpack') +const config = require('../config') +const webpackConfig = require('./webpack.prod.conf') + +const spinner = ora('building for production...') +spinner.start() + +rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { + if (err) throw err + webpack(webpackConfig, function(err, stats) { + spinner.stop() + if (err) throw err + process.stdout.write(stats.toString({ + colors: true, + modules: false, + children: false, + chunks: false, + chunkModules: false + }) + '\n\n') + + if (stats.hasErrors()) { + console.log(chalk.red(' Build failed with errors.\n')) + process.exit(1) + } + + console.log(chalk.cyan(' Build complete.\n')) + console.log(chalk.yellow( + ' Tip: built files are meant to be served over an HTTP server.\n' + + ' Opening index.html over file:// won\'t work.\n' + )) + }) +}) \ No newline at end of file diff --git a/build/check-versions.js b/build/check-versions.js new file mode 100644 index 0000000..3ab7d4a --- /dev/null +++ b/build/check-versions.js @@ -0,0 +1,48 @@ +'use strict' +const chalk = require('chalk') +const semver = require('semver') +const packageConfig = require('../package.json') +const shell = require('shelljs') + +function exec(cmd) { + return require('child_process').execSync(cmd).toString().trim() +} + +const versionRequirements = [{ + name: 'node', + currentVersion: semver.clean(process.version), + versionRequirement: packageConfig.engines.node +}] + +if (shell.which('npm')) { + versionRequirements.push({ + name: 'npm', + currentVersion: exec('npm --version'), + versionRequirement: packageConfig.engines.npm + }) +} + +module.exports = function() { + const warnings = [] + for (let i = 0; i < versionRequirements.length; i++) { + const mod = versionRequirements[i] + if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { + warnings.push(mod.name + ': ' + + chalk.red(mod.currentVersion) + ' should be ' + + chalk.green(mod.versionRequirement) + ) + } + } + + if (warnings.length) { + console.log('') + console.log(chalk.yellow('To use this template, you must update following to modules:')) + console.log() + for (let i = 0; i < warnings.length; i++) { + const warning = warnings[i] + console.log(' ' + warning) + } + console.log() + process.exit(1) + } +} \ No newline at end of file diff --git a/build/dev-client.js b/build/dev-client.js new file mode 100644 index 0000000..0c3533e --- /dev/null +++ b/build/dev-client.js @@ -0,0 +1,10 @@ +/* eslint-disable */ +'use strict' +require('eventsource-polyfill') +var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') + +hotClient.subscribe(function(event) { + if (event.action === 'reload') { + window.location.reload() + } +}) \ No newline at end of file diff --git a/build/dev-server.js b/build/dev-server.js new file mode 100644 index 0000000..7ca3ea4 --- /dev/null +++ b/build/dev-server.js @@ -0,0 +1,105 @@ +'use strict' +require('./check-versions')() + +const config = require('../config') +if (!process.env.NODE_ENV) { + process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV) +} + +const opn = require('opn') +const path = require('path') +const express = require('express') +const webpack = require('webpack') +const proxyMiddleware = require('http-proxy-middleware') +const webpackConfig = require('./webpack.dev.conf') + +// default port where dev server listens for incoming traffic +const port = process.env.PORT || config.dev.port + // automatically open browser, if not set will be false +const autoOpenBrowser = !!config.dev.autoOpenBrowser + // Define HTTP proxies to your custom API backend + // /~https://github.com/chimurai/http-proxy-middleware +const proxyTable = config.dev.proxyTable + +const app = express() +const compiler = webpack(webpackConfig) + +const devMiddleware = require('webpack-dev-middleware')(compiler, { + publicPath: webpackConfig.output.publicPath, + quiet: true +}) + +const hotMiddleware = require('webpack-hot-middleware')(compiler, { + log: false, + heartbeat: 2000 + }) + // force page reload when html-webpack-plugin template changes + // currently disabled until this is resolved: + // /~https://github.com/jantimon/html-webpack-plugin/issues/680 + // compiler.plugin('compilation', function (compilation) { + // compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) { + // hotMiddleware.publish({ action: 'reload' }) + // cb() + // }) + // }) + +// enable hot-reload and state-preserving +// compilation error display +app.use(hotMiddleware) + +// proxy api requests +Object.keys(proxyTable).forEach(function(context) { + let options = proxyTable[context] + if (typeof options === 'string') { + options = { target: options } + } + app.use(proxyMiddleware(options.filter || context, options)) +}) + +// handle fallback for HTML5 history API +app.use(require('connect-history-api-fallback')()) + +// serve webpack bundle output +app.use(devMiddleware) + +// serve pure static assets +const staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) +app.use(staticPath, express.static('./static')) + +const uri = 'http://localhost:' + port + +var _resolve +var _reject +var readyPromise = new Promise((resolve, reject) => { + _resolve = resolve + _reject = reject +}) + +var server +var portfinder = require('portfinder') +portfinder.basePort = port + +console.log('> Starting dev server...') +devMiddleware.waitUntilValid(() => { + portfinder.getPort((err, port) => { + if (err) { + _reject(err) + } + process.env.PORT = port + var uri = 'http://localhost:' + port + console.log('> Listening at ' + uri + '\n') + // when env is testing, don't need open it + if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') { + opn(uri) + } + server = app.listen(port) + _resolve() + }) +}) + +module.exports = { + ready: readyPromise, + close: () => { + server.close() + } +} \ No newline at end of file diff --git a/build/utils.js b/build/utils.js new file mode 100644 index 0000000..a1a6e7d --- /dev/null +++ b/build/utils.js @@ -0,0 +1,72 @@ +'use strict' +const path = require('path') +const config = require('../config') +const ExtractTextPlugin = require('extract-text-webpack-plugin') + +exports.assetsPath = function(_path) { + const assetsSubDirectory = process.env.NODE_ENV === 'production' ? + config.build.assetsSubDirectory : + config.dev.assetsSubDirectory + return path.posix.join(assetsSubDirectory, _path) +} + +exports.cssLoaders = function(options) { + options = options || {} + + const cssLoader = { + loader: 'css-loader', + options: { + minimize: process.env.NODE_ENV === 'production', + sourceMap: options.sourceMap + } + } + + // generate loader string to be used with extract text plugin + function generateLoaders(loader, loaderOptions) { + const loaders = [cssLoader] + if (loader) { + loaders.push({ + loader: loader + '-loader', + options: Object.assign({}, loaderOptions, { + sourceMap: options.sourceMap + }) + }) + } + + // Extract CSS when that option is specified + // (which is the case during production build) + if (options.extract) { + return ExtractTextPlugin.extract({ + use: loaders, + fallback: 'vue-style-loader' + }) + } else { + return ['vue-style-loader'].concat(loaders) + } + } + + // https://vue-loader.vuejs.org/en/configurations/extract-css.html + return { + css: generateLoaders(), + postcss: generateLoaders(), + less: generateLoaders('less'), + sass: generateLoaders('sass', { indentedSyntax: true }), + scss: generateLoaders('sass'), + stylus: generateLoaders('stylus'), + styl: generateLoaders('stylus') + } +} + +// Generate loaders for standalone style files (outside of .vue) +exports.styleLoaders = function(options) { + const output = [] + const loaders = exports.cssLoaders(options) + for (const extension in loaders) { + const loader = loaders[extension] + output.push({ + test: new RegExp('\\.' + extension + '$'), + use: loader + }) + } + return output +} \ No newline at end of file diff --git a/build/vue-loader.conf.js b/build/vue-loader.conf.js new file mode 100644 index 0000000..9f20f1d --- /dev/null +++ b/build/vue-loader.conf.js @@ -0,0 +1,25 @@ +'use strict' +const utils = require('./utils') +const config = require('../config') +const merge = require('webpack-merge') +const isProduction = process.env.NODE_ENV === 'production' + +const cssLoaders = utils.cssLoaders({ + sourceMap: isProduction ? + config.build.productionSourceMap : + config.dev.cssSourceMap, + extract: isProduction +}) +const extendLoaders = { + i18n: '@kazupon/vue-i18n-loader' +} + +module.exports = { + loaders: merge(cssLoaders, extendLoaders), + transformToRequire: { + video: 'src', + source: 'src', + img: 'src', + image: 'xlink:href' + } +} \ No newline at end of file diff --git a/build/webpack.base.conf.js b/build/webpack.base.conf.js new file mode 100644 index 0000000..a1e5641 --- /dev/null +++ b/build/webpack.base.conf.js @@ -0,0 +1,78 @@ +'use strict' +const path = require('path') +const utils = require('./utils') +const config = require('../config') +const vueLoaderConfig = require('./vue-loader.conf') + +function resolve(dir) { + return path.join(__dirname, '..', dir) +} + +module.exports = { + entry: { + app: './src/main.js' + }, + output: { + path: config.build.assetsRoot, + filename: '[name].js', + publicPath: process.env.NODE_ENV === 'production' ? + config.build.assetsPublicPath : + config.dev.assetsPublicPath + }, + resolve: { + extensions: ['.js', '.vue', '.less', '.css', '.scss', '.json'], + alias: { + 'vue$': 'vue/dist/vue.esm.js', + '@': resolve('src'), + 'sysStatic': resolve('src/resources'), + 'sysComponents': resolve('src/components/customCom'), + 'sysPage': resolve('src/page') + } + }, + module: { + rules: [{ + test: /\.(js|vue)$/, + loader: 'eslint-loader', + enforce: "pre", + include: [resolve('src'), resolve('test')], + options: { + formatter: require('eslint-friendly-formatter') + } + }, + { + test: /\.vue$/, + loader: 'vue-loader', + options: vueLoaderConfig + }, + { + test: /\.js$/, + loader: 'babel-loader', + include: [resolve('src'), resolve('test')] + }, + { + test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, + loader: 'url-loader', + options: { + limit: 10000, + name: utils.assetsPath('img/[name].[hash:7].[ext]') + } + }, + { + test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, + loader: 'url-loader', + options: { + limit: 10000, + name: utils.assetsPath('media/[name].[hash:7].[ext]') + } + }, + { + test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, + loader: 'url-loader', + options: { + limit: 10000, + name: utils.assetsPath('fonts/[name].[hash:7].[ext]') + } + } + ] + } +} \ No newline at end of file diff --git a/build/webpack.dev.conf.js b/build/webpack.dev.conf.js new file mode 100644 index 0000000..94ae13b --- /dev/null +++ b/build/webpack.dev.conf.js @@ -0,0 +1,36 @@ +'use strict' +const utils = require('./utils') +const webpack = require('webpack') +const config = require('../config') +const merge = require('webpack-merge') +const baseWebpackConfig = require('./webpack.base.conf') +const HtmlWebpackPlugin = require('html-webpack-plugin') +const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') + +// add hot-reload related code to entry chunks +Object.keys(baseWebpackConfig.entry).forEach(function(name) { + baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) +}) + +module.exports = merge(baseWebpackConfig, { + module: { + rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) + }, + // cheap-module-eval-source-map is faster for development + devtool: '#cheap-module-eval-source-map', + plugins: [ + new webpack.DefinePlugin({ + 'process.env': config.dev.env + }), + // /~https://github.com/glenjamin/webpack-hot-middleware#installation--usage + new webpack.HotModuleReplacementPlugin(), + new webpack.NoEmitOnErrorsPlugin(), + // /~https://github.com/ampedandwired/html-webpack-plugin + new HtmlWebpackPlugin({ + filename: 'index.html', + template: './src/index.html', + inject: true + }), + new FriendlyErrorsPlugin() + ] +}) \ No newline at end of file diff --git a/build/webpack.prod.conf.js b/build/webpack.prod.conf.js new file mode 100644 index 0000000..b02a8ca --- /dev/null +++ b/build/webpack.prod.conf.js @@ -0,0 +1,132 @@ +'use strict' +const path = require('path') +const utils = require('./utils') +const webpack = require('webpack') +const config = require('../config') +const merge = require('webpack-merge') +const baseWebpackConfig = require('./webpack.base.conf') +const CopyWebpackPlugin = require('copy-webpack-plugin') +const HtmlWebpackPlugin = require('html-webpack-plugin') +const ExtractTextPlugin = require('extract-text-webpack-plugin') +const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') + +const env = config.build.env + +const webpackConfig = merge(baseWebpackConfig, { + module: { + rules: utils.styleLoaders({ + sourceMap: config.build.productionSourceMap, + extract: true + }) + }, + devtool: config.build.productionSourceMap ? '#source-map' : false, + output: { + path: config.build.assetsRoot, + filename: utils.assetsPath('js/[name].[chunkhash].js'), + chunkFilename: utils.assetsPath('js/[name].[chunkhash].js') + }, + plugins: [ + // http://vuejs.github.io/vue-loader/en/workflow/production.html + new webpack.DefinePlugin({ + 'process.env': env + }), + new webpack.optimize.UglifyJsPlugin({ + compress: { + warnings: false + }, + sourceMap: false + }), + // extract css into its own file + new ExtractTextPlugin({ + filename: utils.assetsPath('css/[name].[contenthash].css') + }), + // Compress extracted CSS. We are using this plugin so that possible + // duplicated CSS from different components can be deduped. + new OptimizeCSSPlugin({ + cssProcessorOptions: { + 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: './src/index.html', + inject: true, + // minify: { + // removeComments: true, + // collapseWhitespace: true, + // removeAttributeQuotes: true + // // more options: + // // /~https://github.com/kangax/html-minifier#options-quick-reference + // }, + minify: false, + // necessary to consistently work with multiple chunks via CommonsChunkPlugin + chunksSortMode: 'dependency' + }), + // keep module.id stable when vender modules does not change + new webpack.HashedModuleIdsPlugin(), + // split vendor js into its own file + new webpack.optimize.CommonsChunkPlugin({ + name: 'vendor', + minChunks: function(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 + ) + } + }), + // split echarts into its own file + new webpack.optimize.CommonsChunkPlugin({ + async: ['echarts'], + minChunks(module) { + var context = module.context; + return context && (context.indexOf('echarts') >= 0 || context.indexOf('zrender') >= 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', + chunks: ['vendor'] + }), + // copy custom static assets + new CopyWebpackPlugin([ + { + from: path.resolve(__dirname, '../static'), + to: config.build.assetsSubDirectory, + ignore: ['.*'] + } + ]) + ] +}) + +if (config.build.productionGzip) { + var CompressionWebpackPlugin = require('compression-webpack-plugin') + + webpackConfig.plugins.push( + new CompressionWebpackPlugin({ + asset: '[path].gz[query]', + algorithm: 'gzip', + test: new RegExp( + '\\.(' + + config.build.productionGzipExtensions.join('|') + + ')$' + ), + threshold: 10240, + minRatio: 0.8 + }) + ) +} + +if (config.build.bundleAnalyzerReport) { + var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin + webpackConfig.plugins.push(new BundleAnalyzerPlugin()) +} + +module.exports = webpackConfig \ No newline at end of file diff --git a/config/dev.env.js b/config/dev.env.js new file mode 100644 index 0000000..ad81dba --- /dev/null +++ b/config/dev.env.js @@ -0,0 +1,7 @@ +'use strict' +const merge = require('webpack-merge') +const prodEnv = require('./prod.env') + +module.exports = merge(prodEnv, { + NODE_ENV: '"development"' +}) \ No newline at end of file diff --git a/config/index.js b/config/index.js new file mode 100644 index 0000000..ba6d2df --- /dev/null +++ b/config/index.js @@ -0,0 +1,40 @@ +'use strict' +// Template version: 1.1.3 +// see http://vuejs-templates.github.io/webpack for documentation. +const path = require('path') + +module.exports = { + build: { + env: require('./prod.env'), + index: path.resolve(__dirname, '../dist/index.html'), + assetsRoot: path.resolve(__dirname, '../dist'), + assetsSubDirectory: 'static', + assetsPublicPath: './', + productionSourceMap: false, + // Gzip off by default as many popular static hosts such as + // Surge or Netlify already gzip all static assets for you. + // Before setting to `true`, make sure to: + // npm install --save-dev compression-webpack-plugin + productionGzip: false, + productionGzipExtensions: ['js', 'css'], + // Run the build command with an extra argument to + // View the bundle analyzer report after build finishes: + // `npm run build --report` + // Set to `true` or `false` to always turn it on or off + bundleAnalyzerReport: process.env.npm_config_report + }, + dev: { + env: require('./dev.env'), + port: process.env.PORT || 9000, + autoOpenBrowser: true, + assetsSubDirectory: 'static', + assetsPublicPath: '/', + proxyTable: {}, + // CSS Sourcemaps off by default because relative paths are "buggy" + // with this option, according to the CSS-Loader README + // (/~https://github.com/webpack/css-loader#sourcemaps) + // In our experience, they generally work as expected, + // just be aware of this issue when enabling this option. + cssSourceMap: false + } +} \ No newline at end of file diff --git a/config/prod.env.js b/config/prod.env.js new file mode 100644 index 0000000..ba577e8 --- /dev/null +++ b/config/prod.env.js @@ -0,0 +1,4 @@ +'use strict' +module.exports = { + NODE_ENV: '"production"' +} \ No newline at end of file diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..a0cfad9 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,5 @@ +{ + "include": [ + "./src/**/*" + ] +} \ No newline at end of file diff --git a/mock/echarts.js b/mock/echarts.js new file mode 100644 index 0000000..5abacc4 --- /dev/null +++ b/mock/echarts.js @@ -0,0 +1,28 @@ +/** + * 因Mock自身原因,不能直接模拟不带属性名的数组。这里需要的是[1,2,3],而不是{data: [1,2,3]} + * 以下被注释掉的方法不可取,因每次获取后,返回值不变 + */ + +// import Mock from 'mockjs' + +// var data = Mock.mock({ +// "data|7": [ +// '@natural(60, 100)' +// ] +// }) + +// export default [{ +// path: '/charts', +// data: data.data +// }] + +export default [{ + path: '/charts', + data: function(){ + var res = [] + for(var i = 0; i < 7; i++){ + res.push(parseInt(Math.random()*100)+1) + } + return res + } +}] diff --git a/mock/index.js b/mock/index.js new file mode 100644 index 0000000..c18aaa6 --- /dev/null +++ b/mock/index.js @@ -0,0 +1,13 @@ +import Mock from 'mockjs' +import navlist from './navlist' +import login from './login' +import echarts from './echarts' +// import {datasource} from './datasource.js'; + +let data = [].concat(navlist, login, echarts) + +data.forEach(function(res){ + Mock.mock(res.path, res.data) +}) + +export default Mock \ No newline at end of file diff --git a/mock/login.js b/mock/login.js new file mode 100644 index 0000000..764271c --- /dev/null +++ b/mock/login.js @@ -0,0 +1,13 @@ +var data = { + 'login': '@boolean', + 'validate': '@boolean', + 'message': '这里是登录提交后错误提示信息@increment', + 'uid': '@id', + 'name': '@cname', + 'token': '@guid' +} + +export default [{ + path: '/login', + data: data +}] \ No newline at end of file diff --git a/mock/navlist.js b/mock/navlist.js new file mode 100644 index 0000000..50f3754 --- /dev/null +++ b/mock/navlist.js @@ -0,0 +1,118 @@ +var data = [ + { + path: '/home', + name: '首页' + }, + { + name: '系统组件', + child: [ + { + name: '介绍', + path: '/components' + }, + { + name: '功能类', + child: [ + { + path: '/components/permission', + name: '详细鉴权' + }, + { + path: '/components/pageTable', + name: '表格分页' + } + ] + }, + { + name: '布局类', + child: [ + { + path: '/components/pageTitle', + name: '页面标题' + }, + { + name: '测试类1', + child: [ + { + path: '/components/pageSection', + name: '子区域' + } + ] + }, + { + path: '/components/pageSearch', + name: '搜索条' + }, + { + name: '测试类2', + child: [ + { + path: '/components/pageToolbar', + name: '工具条' + } + ] + } + ] + }, + { + name: '辅助类', + child: [ + { + path: '/components/pageNotes', + name: '引用说明' + } + ] + } + ] + }, + // { + // name: '表格', + // child: [ + // { + // path: '/table', + // name: '静态表格', + // permission: ['view','import'] + // } + // ] + // }, + // { + // name: '表单', + // child: [ + // { + // path: '/form', + // name: '静态表格' + // } + // ] + // }, + { + name: '完整示例', + child: [ + { + path: '/example/table', + name: '列表页面', + permission: ['outport'] + }, + { + path: '/example/charts', + name: '图表页面' + }, + { + path: '/example/map', + name: '地图页面' + } + ] + }, + { + path: '/i18n', + name: '国际化' + }, + { + path: '/theme', + name: '主题切换' + } +] + +export default [{ + path: '/user/navlist', + data: data +}] \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..9bebf32 --- /dev/null +++ b/package.json @@ -0,0 +1,89 @@ +{ + "name": "vue-backend", + "version": "0.0.1", + "description": "前后端分离VUE类模板项目工程", + "author": "harsima", + "private": true, + "scripts": { + "dev": "node build/dev-server.js", + "start": "node build/dev-server.js", + "build": "node build/build.js" + }, + "dependencies": { + "axios": "^0.16.2", + "echarts": "^3.7.2", + "element-ui": "^1.4.6", + "js-cookie": "^2.2.0", + "lodash": "^4.17.4", + "mockjs": "^1.0.1-beta3", + "nprogress": "^0.2.0", + "vue": "^2.5.2", + "vue-i18n": "^7.3.2", + "vue-router": "^2.6.0", + "vuex": "^2.4.1" + }, + "devDependencies": { + "@kazupon/vue-i18n-loader": "^0.2.1", + "autoprefixer": "^7.1.6", + "babel-core": "^6.26.0", + "babel-eslint": "^8.0.1", + "babel-loader": "^7.1.2", + "babel-polyfill": "^6.26.0", + "babel-preset-env": "^1.6.1", + "babel-preset-stage-2": "^6.22.0", + "babel-register": "^6.26.0", + "chalk": "^2.3.0", + "connect-history-api-fallback": "^1.4.0", + "copy-webpack-plugin": "^4.2.0", + "css-loader": "^0.28.7", + "element-theme-default": "^1.4.8", + "eslint": "^3.19.0", + "eslint-config-standard": "^10.2.1", + "eslint-friendly-formatter": "^3.0.0", + "eslint-import-resolver-webpack": "^0.8.3", + "eslint-loader": "^1.7.1", + "eslint-plugin-html": "^3.0.0", + "eslint-plugin-import": "^2.7.0", + "eslint-plugin-node": "^5.2.0", + "eslint-plugin-promise": "^3.4.0", + "eventsource-polyfill": "^0.9.6", + "express": "^4.16.2", + "extract-text-webpack-plugin": "^3.0.2", + "file-loader": "^1.1.4", + "friendly-errors-webpack-plugin": "^1.6.1", + "html-webpack-plugin": "^2.30.1", + "http-proxy-middleware": "^0.17.3", + "less": "^2.7.3", + "less-loader": "^4.0.5", + "node-sass": "^4.5.3", + "opn": "^5.1.0", + "optimize-css-assets-webpack-plugin": "^3.2.0", + "ora": "^1.2.0", + "portfinder": "^1.0.13", + "rimraf": "^2.6.2", + "sass-loader": "^6.0.6", + "semver": "^5.4.1", + "shelljs": "^0.7.6", + "url-loader": "^0.5.8", + "vue-loader": "^13.3.0", + "vue-style-loader": "^3.0.3", + "vue-template-compiler": "^2.5.2", + "webpack": "^3.8.1", + "webpack-bundle-analyzer": "^2.9.0", + "webpack-dev-middleware": "^1.12.0", + "webpack-hot-middleware": "^2.20.0", + "webpack-merge": "^4.1.0" + }, + "engines": { + "node": ">= 4.0.0", + "npm": ">= 3.0.0" + }, + "browserslist": [ + "> 1%", + "Android >= 4.4", + "iOS >= 8", + "Chrome >= 46", + "ff >= 43", + "not ie <= 8" + ] +} diff --git a/src/components/customCom/global/install.js b/src/components/customCom/global/install.js new file mode 100644 index 0000000..e69de29 diff --git a/src/components/customCom/locale/signalGroup/dialogView.vue b/src/components/customCom/locale/signalGroup/dialogView.vue new file mode 100644 index 0000000..69ec4d5 --- /dev/null +++ b/src/components/customCom/locale/signalGroup/dialogView.vue @@ -0,0 +1,121 @@ + + + + diff --git a/src/components/customCom/locale/signalGroup/signalGroup.vue b/src/components/customCom/locale/signalGroup/signalGroup.vue new file mode 100644 index 0000000..62aee88 --- /dev/null +++ b/src/components/customCom/locale/signalGroup/signalGroup.vue @@ -0,0 +1,94 @@ + + + + + diff --git a/src/components/customCom/locale/signalGroup/signalItem.1.vue b/src/components/customCom/locale/signalGroup/signalItem.1.vue new file mode 100644 index 0000000..4b7af59 --- /dev/null +++ b/src/components/customCom/locale/signalGroup/signalItem.1.vue @@ -0,0 +1,125 @@ + + + + + diff --git a/src/components/customCom/locale/signalGroup/signalItem.vue b/src/components/customCom/locale/signalGroup/signalItem.vue new file mode 100644 index 0000000..9128dd1 --- /dev/null +++ b/src/components/customCom/locale/signalGroup/signalItem.vue @@ -0,0 +1,126 @@ + + + + + diff --git a/src/components/platformCom/hasPermission/index.js b/src/components/platformCom/hasPermission/index.js new file mode 100644 index 0000000..42a8cd1 --- /dev/null +++ b/src/components/platformCom/hasPermission/index.js @@ -0,0 +1,18 @@ +const hasPermission = { + // eslint-disable-next-line + install (Vue, options){ + Vue.mixin({ + methods:{ + hasPermission(data){ + let permissionList = this.$route.meta.permission + if(permissionList && permissionList.length && permissionList.includes(data)){ + return true + } + return false + } + } + }) + } +} + +export default hasPermission diff --git a/src/components/platformCom/install.js b/src/components/platformCom/install.js new file mode 100644 index 0000000..01abab9 --- /dev/null +++ b/src/components/platformCom/install.js @@ -0,0 +1,29 @@ +// 组件全局注册 +import Vue from 'vue' + +import HasPermission from './hasPermission' +import PageNotes from './pageNotes' +import PageTitle from './pageTitle' +import PageToolbar from './PageToolbar' +import PageSection from './PageSection' +import PageTable from './PageTable' +import PageSearch from './PageSearch' + +// 形成组件库 +const components = [ + HasPermission, + PageNotes, + PageTitle, + PageSection, + PageTable, + PageToolbar, + PageSearch +] + +// 注册全局组件 +components.map((com) =>{ + Vue.use(com) + // Vue.component(com.name, com) +}) + +export default components \ No newline at end of file diff --git a/src/components/platformCom/pageNotes/index.js b/src/components/platformCom/pageNotes/index.js new file mode 100644 index 0000000..6b252db --- /dev/null +++ b/src/components/platformCom/pageNotes/index.js @@ -0,0 +1,7 @@ +import PageNotes from './main' + +PageNotes.install = function(Vue){ + Vue.component(PageNotes.name, PageNotes) +} + +export default PageNotes; \ No newline at end of file diff --git a/src/components/platformCom/pageNotes/main.vue b/src/components/platformCom/pageNotes/main.vue new file mode 100644 index 0000000..868972a --- /dev/null +++ b/src/components/platformCom/pageNotes/main.vue @@ -0,0 +1,24 @@ + + + + + + \ No newline at end of file diff --git a/src/components/platformCom/pageSearch/index.js b/src/components/platformCom/pageSearch/index.js new file mode 100644 index 0000000..8e52cc0 --- /dev/null +++ b/src/components/platformCom/pageSearch/index.js @@ -0,0 +1,7 @@ +import PageSearch from './main' + +PageSearch.install = function(Vue){ + Vue.component(PageSearch.name, PageSearch) +} + +export default PageSearch; \ No newline at end of file diff --git a/src/components/platformCom/pageSearch/main.vue b/src/components/platformCom/pageSearch/main.vue new file mode 100644 index 0000000..5172992 --- /dev/null +++ b/src/components/platformCom/pageSearch/main.vue @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/src/components/platformCom/pageSection/index.js b/src/components/platformCom/pageSection/index.js new file mode 100644 index 0000000..6746296 --- /dev/null +++ b/src/components/platformCom/pageSection/index.js @@ -0,0 +1,7 @@ +import PageSection from './main' + +PageSection.install = function(Vue){ + Vue.component(PageSection.name, PageSection) +} + +export default PageSection; \ No newline at end of file diff --git a/src/components/platformCom/pageSection/main.vue b/src/components/platformCom/pageSection/main.vue new file mode 100644 index 0000000..1c2d5c3 --- /dev/null +++ b/src/components/platformCom/pageSection/main.vue @@ -0,0 +1,44 @@ + + + + + \ No newline at end of file diff --git a/src/components/platformCom/pageTable/index.js b/src/components/platformCom/pageTable/index.js new file mode 100644 index 0000000..1043ddc --- /dev/null +++ b/src/components/platformCom/pageTable/index.js @@ -0,0 +1,7 @@ +import PageTable from './main' + +PageTable.install = function(Vue){ + Vue.component(PageTable.name, PageTable) +} + +export default PageTable; \ No newline at end of file diff --git a/src/components/platformCom/pageTable/main.vue b/src/components/platformCom/pageTable/main.vue new file mode 100644 index 0000000..6e9c018 --- /dev/null +++ b/src/components/platformCom/pageTable/main.vue @@ -0,0 +1,85 @@ + + + + + \ No newline at end of file diff --git a/src/components/platformCom/pageTitle/index.js b/src/components/platformCom/pageTitle/index.js new file mode 100644 index 0000000..1d61852 --- /dev/null +++ b/src/components/platformCom/pageTitle/index.js @@ -0,0 +1,7 @@ +import PageTitle from './main' + +PageTitle.install = function(Vue){ + Vue.component(PageTitle.name, PageTitle) +} + +export default PageTitle; \ No newline at end of file diff --git a/src/components/platformCom/pageTitle/main.vue b/src/components/platformCom/pageTitle/main.vue new file mode 100644 index 0000000..c7bddcf --- /dev/null +++ b/src/components/platformCom/pageTitle/main.vue @@ -0,0 +1,28 @@ + + + + + + \ No newline at end of file diff --git a/src/components/platformCom/pageToolbar/index.js b/src/components/platformCom/pageToolbar/index.js new file mode 100644 index 0000000..6b1d752 --- /dev/null +++ b/src/components/platformCom/pageToolbar/index.js @@ -0,0 +1,7 @@ +import PageToolbar from './main' + +PageToolbar.install = function(Vue){ + Vue.component(PageToolbar.name, PageToolbar) +} + +export default PageToolbar; \ No newline at end of file diff --git a/src/components/platformCom/pageToolbar/main.vue b/src/components/platformCom/pageToolbar/main.vue new file mode 100644 index 0000000..7780207 --- /dev/null +++ b/src/components/platformCom/pageToolbar/main.vue @@ -0,0 +1,32 @@ + + + + + \ No newline at end of file diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..7c8ac2a --- /dev/null +++ b/src/index.html @@ -0,0 +1,15 @@ + + + + + + + + + + 欢迎光临 + + +
+ + diff --git a/src/index.vue b/src/index.vue new file mode 100644 index 0000000..85b3a5b --- /dev/null +++ b/src/index.vue @@ -0,0 +1,66 @@ + + + diff --git a/src/lang/en.js b/src/lang/en.js new file mode 100644 index 0000000..35142bf --- /dev/null +++ b/src/lang/en.js @@ -0,0 +1,4 @@ +export default { + editpassword: 'Edit Password', + logout: 'Logout' +} \ No newline at end of file diff --git a/src/lang/zh-cn.js b/src/lang/zh-cn.js new file mode 100644 index 0000000..8c7be50 --- /dev/null +++ b/src/lang/zh-cn.js @@ -0,0 +1,4 @@ +export default { + editpassword: '修改密码', + logout: '退出登录' +} \ No newline at end of file diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..bdb8d1c --- /dev/null +++ b/src/main.js @@ -0,0 +1,27 @@ +// 引入babel编译环境 +import 'babel-polyfill' +// 引入Mock +import '../mock/index.js' +// 框架引入 +import Vue from "vue" +import router from './router' +import store from './store' +import axios from './util/ajax' +import ElementUI from 'element-ui' +import 'element-ui/lib/theme-default/index.css' +import i18n from './util/i18n' +import App from './index' +// 全局组件 +import './components/platformCom/install' + +// 注册组件到Vue +Vue.prototype.$axios = axios; +Vue.use(ElementUI) + +new Vue({ + i18n, + // axios, + router, + store, + render: h => h(App) +}).$mount('#app') \ No newline at end of file diff --git a/src/page/components/assist/pageNotes.vue b/src/page/components/assist/pageNotes.vue new file mode 100644 index 0000000..3babdb0 --- /dev/null +++ b/src/page/components/assist/pageNotes.vue @@ -0,0 +1,42 @@ + + + \ No newline at end of file diff --git a/src/page/components/function/pageTable.vue b/src/page/components/function/pageTable.vue new file mode 100644 index 0000000..0c7a1f4 --- /dev/null +++ b/src/page/components/function/pageTable.vue @@ -0,0 +1,78 @@ + + + \ No newline at end of file diff --git a/src/page/components/function/permission.vue b/src/page/components/function/permission.vue new file mode 100644 index 0000000..dbe6c0d --- /dev/null +++ b/src/page/components/function/permission.vue @@ -0,0 +1,40 @@ + + + \ No newline at end of file diff --git a/src/page/components/index.vue b/src/page/components/index.vue new file mode 100644 index 0000000..fc0b1fc --- /dev/null +++ b/src/page/components/index.vue @@ -0,0 +1,34 @@ + \ No newline at end of file diff --git a/src/page/components/ui/pageSearch.vue b/src/page/components/ui/pageSearch.vue new file mode 100644 index 0000000..1ad74d2 --- /dev/null +++ b/src/page/components/ui/pageSearch.vue @@ -0,0 +1,42 @@ + + + \ No newline at end of file diff --git a/src/page/components/ui/pageSection.vue b/src/page/components/ui/pageSection.vue new file mode 100644 index 0000000..00bea50 --- /dev/null +++ b/src/page/components/ui/pageSection.vue @@ -0,0 +1,42 @@ + + + \ No newline at end of file diff --git a/src/page/components/ui/pageTitle.vue b/src/page/components/ui/pageTitle.vue new file mode 100644 index 0000000..edaa83f --- /dev/null +++ b/src/page/components/ui/pageTitle.vue @@ -0,0 +1,42 @@ + + + \ No newline at end of file diff --git a/src/page/components/ui/pageToolbar.vue b/src/page/components/ui/pageToolbar.vue new file mode 100644 index 0000000..2e25009 --- /dev/null +++ b/src/page/components/ui/pageToolbar.vue @@ -0,0 +1,45 @@ + + + \ No newline at end of file diff --git a/src/page/error/401.vue b/src/page/error/401.vue new file mode 100644 index 0000000..c91b876 --- /dev/null +++ b/src/page/error/401.vue @@ -0,0 +1,16 @@ + + + \ No newline at end of file diff --git a/src/page/error/403.vue b/src/page/error/403.vue new file mode 100644 index 0000000..8b73ba2 --- /dev/null +++ b/src/page/error/403.vue @@ -0,0 +1,16 @@ + + + \ No newline at end of file diff --git a/src/page/error/404.vue b/src/page/error/404.vue new file mode 100644 index 0000000..9d08c07 --- /dev/null +++ b/src/page/error/404.vue @@ -0,0 +1,16 @@ + + + diff --git a/src/page/error/500.vue b/src/page/error/500.vue new file mode 100644 index 0000000..7f924c8 --- /dev/null +++ b/src/page/error/500.vue @@ -0,0 +1,16 @@ + + + diff --git a/src/page/error/error.vue b/src/page/error/error.vue new file mode 100644 index 0000000..4f55938 --- /dev/null +++ b/src/page/error/error.vue @@ -0,0 +1,18 @@ + + + + + \ No newline at end of file diff --git a/src/page/example/charts/chart1.vue b/src/page/example/charts/chart1.vue new file mode 100644 index 0000000..60a486f --- /dev/null +++ b/src/page/example/charts/chart1.vue @@ -0,0 +1,92 @@ + + + + \ No newline at end of file diff --git a/src/page/example/charts/charts.vue b/src/page/example/charts/charts.vue new file mode 100644 index 0000000..9111b54 --- /dev/null +++ b/src/page/example/charts/charts.vue @@ -0,0 +1,42 @@ + + + diff --git a/src/page/example/map/map.vue b/src/page/example/map/map.vue new file mode 100644 index 0000000..2a0f8dc --- /dev/null +++ b/src/page/example/map/map.vue @@ -0,0 +1,31 @@ + + + + + diff --git a/src/page/example/map/map1.vue b/src/page/example/map/map1.vue new file mode 100644 index 0000000..2a1378b --- /dev/null +++ b/src/page/example/map/map1.vue @@ -0,0 +1,32 @@ + + + + + diff --git a/src/page/example/table.vue b/src/page/example/table.vue new file mode 100644 index 0000000..6a2b472 --- /dev/null +++ b/src/page/example/table.vue @@ -0,0 +1,177 @@ + + + diff --git a/src/page/form/form.vue b/src/page/form/form.vue new file mode 100644 index 0000000..bcc1125 --- /dev/null +++ b/src/page/form/form.vue @@ -0,0 +1,14 @@ + diff --git a/src/page/home/home.vue b/src/page/home/home.vue new file mode 100644 index 0000000..968c9ed --- /dev/null +++ b/src/page/home/home.vue @@ -0,0 +1,86 @@ + \ No newline at end of file diff --git a/src/page/i18n/i18n.vue b/src/page/i18n/i18n.vue new file mode 100644 index 0000000..efd7e93 --- /dev/null +++ b/src/page/i18n/i18n.vue @@ -0,0 +1,202 @@ + +{ + "en": { + "test": "This is test text. This page's international language use single file components. " + }, + "zh": { + "test": "这是测试文字。本页的国际化设置使用的单文件组件形式。" + } +} + + + + + \ No newline at end of file diff --git a/src/page/layout/Header.vue b/src/page/layout/Header.vue new file mode 100644 index 0000000..527fc14 --- /dev/null +++ b/src/page/layout/Header.vue @@ -0,0 +1,192 @@ + + + + + \ No newline at end of file diff --git a/src/page/layout/Sidenav.1.vue b/src/page/layout/Sidenav.1.vue new file mode 100644 index 0000000..5ac014d --- /dev/null +++ b/src/page/layout/Sidenav.1.vue @@ -0,0 +1,173 @@ + + + + + + diff --git a/src/page/layout/Sidenav.vue b/src/page/layout/Sidenav.vue new file mode 100644 index 0000000..b67c96e --- /dev/null +++ b/src/page/layout/Sidenav.vue @@ -0,0 +1,180 @@ + + + + + diff --git a/src/page/layout/layout.vue b/src/page/layout/layout.vue new file mode 100644 index 0000000..8103789 --- /dev/null +++ b/src/page/layout/layout.vue @@ -0,0 +1,66 @@ + + + + + diff --git a/src/page/layout/navItem.1.vue b/src/page/layout/navItem.1.vue new file mode 100644 index 0000000..8e7cd76 --- /dev/null +++ b/src/page/layout/navItem.1.vue @@ -0,0 +1,37 @@ + + + diff --git a/src/page/layout/navItem.vue b/src/page/layout/navItem.vue new file mode 100644 index 0000000..1a6ef71 --- /dev/null +++ b/src/page/layout/navItem.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/page/login/login.vue b/src/page/login/login.vue new file mode 100644 index 0000000..b478cd5 --- /dev/null +++ b/src/page/login/login.vue @@ -0,0 +1,228 @@ + + + + + + diff --git a/src/page/table/table.vue b/src/page/table/table.vue new file mode 100644 index 0000000..0de1555 --- /dev/null +++ b/src/page/table/table.vue @@ -0,0 +1,111 @@ + + + \ No newline at end of file diff --git a/src/page/themeChange/themeChange.vue b/src/page/themeChange/themeChange.vue new file mode 100644 index 0000000..ec8b05c --- /dev/null +++ b/src/page/themeChange/themeChange.vue @@ -0,0 +1,78 @@ + + + diff --git a/src/resources/css/reset.scss b/src/resources/css/reset.scss new file mode 100644 index 0000000..3beab01 --- /dev/null +++ b/src/resources/css/reset.scss @@ -0,0 +1,118 @@ +@import '~sysStatic/css/theme/theme.scss'; + +* { + box-sizing: border-box; +} +html, body, div, section, header, footer, aside, ul, ol, li, table, tr, th, td, button, input, textarea, select, h1, h2, h3, h4, h5, h6, em, i, strong, p, span, blockquote { + margin: 0; + padding: 0; +} +h1, h2, h3, h4, h5, h6, em, th, i, strong, input, textarea, button, select { + font-weight: normal; + font-style: normal; + font-size: 100%; +} +ul, ol { + list-style: none; + vertical-align: top; +} +table, td, th { + border-collapse: collapse; + border-spacing: 0; +} +input, button, select, textarea { + outline: none; + background: none; +} +textarea { + resize: none; +} +img, a img { + border: none; + vertical-align: top; +} +a, a:link, a:active, a:visited { + text-decoration: none; + color: #666; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +a:hover { + color: $themeColor; + text-decoration: none; +} +html { + height: 100%; +} +body { + font-size: $systemFontSize; + font-family: $systemFontFamily; + color: $systemFontColor; + height: 100%; +} +.f-cb:after { + display: block; + clear: both; + visibility: hidden; + height: 0; + overflow: hidden; + content: "."; +} +.f-cb { + zoom: 1; +} +.fl { + float: left; +} +.fr { + float: right; +} +.fc { + margin: 0 auto; +} +.vertical-middle { + vertical-align: middle; +} + +/**显示隐藏**/ + +.hidden { + display: none; +} +.clear { + clear: both; +} +.overflow { + overflow: hidden; +} + +/**定位**/ + +.posR { + position: relative; +} +.posA { + position: absolute; +} +.posF { + position: fixed; +} +.fb { + font-weight: bold; +} +.textL { + text-align: left; +} +.textC { + text-align: center; +} +.textR { + text-align: right; +} +.text2em { + text-indent: 2em +} +.word-hidden { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} \ No newline at end of file diff --git a/src/resources/css/theme/default/default.scss b/src/resources/css/theme/default/default.scss new file mode 100644 index 0000000..a601df1 --- /dev/null +++ b/src/resources/css/theme/default/default.scss @@ -0,0 +1,34 @@ +// Basic Color +//------------------------------- +$white: #fff; +$lighterGray: #eee; +$lightGray: #ccc; +$neutralGray: #aaa; +$gray: #999; +$darkGray: #666; +$darkerGray: #333; + +// 主题基本颜色 +//------------------------------- +$themeColor: #1F2D3D; +$borderColor: #d2d2d2; +$shadowColor: rgba(0,0,0,0); +$commonBgColor: #f2f2f2; + +// 组件颜色 +//------------------------------- + +// 顶部标题栏颜色 +$headerBgColor: $themeColor; +$headerBorderColor: none; +$headerShadow: $shadowColor; +$headerColor: #c2c2c2; + +// 左侧导航颜色 +$sidenavBgColor: #324157; + +// 右侧主体内容背景色 +$mainContentBgColor: #fff; + +$tipsBgColor: $commonBgColor; +$tipsBorderColor: $sidenavBgColor; \ No newline at end of file diff --git a/src/resources/css/theme/theme.scss b/src/resources/css/theme/theme.scss new file mode 100644 index 0000000..446f832 --- /dev/null +++ b/src/resources/css/theme/theme.scss @@ -0,0 +1,10 @@ +@import './default/default.scss'; + +// 系统全局设置,不包括具体细节颜色设置 +//------------------------------- +$systemFontSize: 14px; +$systemFontFamily: "Helvetica", "Microsoft Yahei", san-serif; +$systemFontColor: #333; +$headerHeight: 60px; +$leftNavWidth: 160px; +$commomSpace: 10px; \ No newline at end of file diff --git a/src/resources/images/layout-left.png b/src/resources/images/layout-left.png new file mode 100644 index 0000000000000000000000000000000000000000..0d802d8bc9bc450144adb75f52dcce87818dddb8 GIT binary patch literal 2399 zcmds1OK1~87~Yy{rP@;PqC#QZiVrZ^Y~DLG_K{6(un9E{G@!&DT{Os)T{r~^{^M5m&(}^2> zz2|!whUtqs9r zk_a|a7%$XMaXO0$wzAj&kqEdltLh5QTUV>_cpS!bi%7bRVq%!30bHu8KyM)A@dd^` zf;SZ4`Dk!FD*6TAL@*)*e1V`RTK5&Pyr?0a)P0qvueYtQtpv@WnMGu(OGue8u?DIY zL$y5@ciVV1U!^@4zO64u$#8aGkMy~|Ma5$;8>*#04c#N1iru8Du6%j+mfnaH(^IKv zrBd15-3=YQSZA2yA7kQJs<8KC??WFm+8rJHgYTS5tnEJd`h9C@X!X{&ZU6@ckJ?86 zz+ltFo{j#dZ9BxCrj@$39SvJ8Go_}Dl9h7P030Pv`|or@*HJF^y3Qr{)P7aySo!sS zf4vM#zi-~(c}&@@mTgdJv!71!GNh9hm!M<@w#syllI;lT4A|{zi9OqAX!B~7)=C7B z9z(s-!;|O$SVrjJX10*+)_zs5o!QJ*dVJI=H?u`ETfIRoFYud}-DjDD=icJ!!AlSA O2QC&(h_A-)uKfiNML(1P literal 0 HcmV?d00001 diff --git a/src/resources/images/layout-top.png b/src/resources/images/layout-top.png new file mode 100644 index 0000000000000000000000000000000000000000..ad84f2737672b61cca881ee2d566e85cb719a9a5 GIT binary patch literal 2043 zcmdT^O=}ZD7@js_YoVnFFA9ZmE5(Az?rfSgyEL{*HnD-Ggf!Be#O>}hUE1AQcc&&T zB7R)z4^U9>Qg0r_o&-Gzp49eIyhuS*@KB225AaZD+a#NVkrGgG;9=hx-j8SA_nEz$ zpT5}JbGior(3_o93IGHs0G(&M1MEb7{@@+^oTBLxogwqIqBO;5fK`3v z>RUX(>xac+T9 zTju#nr4p)yL&PcbNRlL85P4AyGLN9UVo|jkwA{gZ1_isCW7yOn7W6Wzb7YyuImYzx z3Z~siYq_;Hv4-(g)#g!1@UB#M%;kRXYMKpimlm+k_m_#?;);#=0(Qx=qp`uw4|=6+ zIptuL5~oPWQoW1$1wx6tKx~*w!E>{QrIU&~eBhqT$yv*#s-@wq66aWgkYVWZh$tpg z8A+7Fu_!|6(HKgNDkvhPMkSPtMl|j6+O# zaAVnM%|&RLuNJGf=7L(r@{A1c&9!OH^&=)8&uplcZ5q1A78AR}RQ==O`zU)6$MaLg z^#1<-*49>R@5vnij$O_wiDGr<+fJevfbPJ?mro-@Z(cvX_w4J9O>hZyto12f%~%g8 zT|Txu)&mXP+6CJ_Cg{ywA5fm4KKcis>|?F3f51oE<%XK8dv?A0XOsO|4wt<-+;yE# z{B3G&cB0(b+!)VpyE$z#IQraKH)?Y!q4GboJ%!`4ga6~vWQOI}U;xR7id=Wq!7?oZbpi=9-N#Q1A( zQ|WF@S5GFLK_2_F2WsM^WM))g@R$}@`PidUsfbCVrKP30q`A8Y#cODEPft&ps~gSD zjS3>Dk_>^An@$x-=8Q80B9cTgPbB3D1!SC&n;=Y;`q%@fqbcx3Z)pXRv1Jf-o#h=~6k%ICk0mPn(JcYgnrSQ3*VLTFKlM3^d01cghUgG-5+0b+zJ6^dho z!gb@fxEvKqg%VUKA_oMJ=g0B{Ny0SA0)2Qy1T#b+k#YrzNJyZMJs@!5@sgMeJ>3>9 z^jJ(^?B*6orw4g>27r6=SmYn<#t5bd1$&NT1BHpHd_*7}$0ohQx_uCfcLHAolmihl zZv&DPEEe*~`iz;p4|?$k{vh8NHtEA&TtA4V0W&nbuJ6@(d)bL`;wJ5ThlXA>Sa;xUGaj;qtH7q5xBa|k53hp`rFNQ zJgSSjTg4?e?y2N0M^9A5BvOlQT4i*>t%$EK-8#MNqRlQBDL3jz!%5rSE?oQh-pU_t zow&9<`SjqyKCef8ZPy&!f0lT%*pjt6RLUR}9dC(gXwaxLy3s+el1D!#O^s3@oRQ6qG( zVa~Q-OSO^n9&<%cPY=&`GIc^&#pRTL=}sHrPnS~Ks#9w_i{nZzg|iJyLhGiiyB%7% z{%QbzCfB7fTJ2g7bp4oZiyykjwMA+zRWU^D+h+voaK)rkpY-?6LQP;NYv@pm)NbF?{!f99%P!V28Q?jdum`y_&#F1RYTjnBj0%UM zJ=!jxJVP@%?7&%Y8~J6kYhr1&3&5*7yrZJazDVWQ^sJv(HIuEe#F%DKtk6rn$pKES zXnc0VqYYr{N>BN@Tn}0^X=B2-yY$I5|Sr)dzV0>_$2!E+?$;}}>EB4K)zDfIVX+wn}T)p(}B2?I=6^Ed=X*tdyv({6DY60=@C;)?MRP`MN zu7q^<>zbuVXza)X ziwPu5(DhVuQJ${8n+IKQlrIF7wu*CKbYMhWkVi8@kZrDQl3)_+iB%2ceN9Ng!NvQFIDfq zo`dS9C>ubt0HQJrD7tZ|d}NTfE^BeDdeY=vbLIYW)|RgxY5*r>en0bCvkn^4nXWm0 zsCbcmZEc^}Yv8A!L`?Dh1M!z6+vLyP%AQ-1u!b*KXBXM>1AFC#_kQ_h!7k|gc}gwt z#l#j(D`KrjsY^Ew`YRgHe1a+D&eg3ZVq5(cRaJ$}CMau~ayy8efo<4rq4@3^Z^;+w+fSq4+%nRc%T6=SfU-ms3 z*ULp&+?>yaX4F-ZzgX+vEV2rT+8s&2!4S3f-+}ym+zfn$s zG!3STT9ur{25+%kI;xva;XKIK`KaVG*oDErp}N_6T-uk-PgZJWdNT8J-H)ki4gu>* zU>GZ^4>K0Nh>XS0s*80*SZAgzD|=|f7N$+3!k|dn4t8u++2=S?(R(EI*YoX7Ppi5+ zei$@_zJqf%_PApmQ6BNGrHE4c^7*BrY&#BezQY9qRk$6Z$X=x~gq*Ri0@m!t8Mfy{ z!_^#o4#{t!t7={rOJ6)D!PeV-oMGLmJKa3w$pwp%gOR07W8576YI?n>q4%Z@#swLL!LL8}TMj4Xj#;5}XHfrak&!ET;UK@AlTRPwM+ zA7%2%x+6EMKzd@{1?{dlNd^rwqJ;T_nF--YBLy)5crt-B#BI79{B^5L_lV=5R{^sZ zjL>?y3#_xn%qD}~pa!cY4)8wJT!4oyv6QnF+7*L#)!FSC%t1!a)ybV)z$>X7*a$CK z=6yi9lHq$hG5*aUnz>>4W;vL~ah5lZuWD!BdHJZl>S5+JhpR(PS5^yq(aB)8JEK5d zMgpawaKO|C!(CO5`(T6O03TEoP-|r1bHo|-16N>30-rb(aE!+hsJJ08`!S;;;dX`NNqiVp71IJHs9IVDbKpJ3D@=4fOjOAzugw}^@WRS6b zMKNNlfUdQno{yNPx0U~?9_l~p`eUtZ&nAL$>feAx>BSc4wWjH%hfjROhHS3YU;keFhi}G}Glye0O)!|vxw`V(kn%hD&)Sfn$iU require.ensure([], () => r(require('../page/layout/layout')), 'layout'), + children: [] + }, + { + path: '/table', + meta:{ + permission:[] + }, + component: r => require.ensure([], () => r(require('../page/table/table')), 'table') + }, + { + path: '/form', + meta:{ + permission:[] + }, + component: r => require.ensure([], () => r(require('../page/form/form')), 'form'), + }, + { + path: '/components', + meta:{ + permission:[] + }, + component: r => require.ensure([], () => r(require('../page/components/index')), 'sysComponents'), + }, + { + path: '/components/permission', + meta:{ + permission:[] + }, + component: r => require.ensure([], () => r(require('../page/components/function/permission')), 'sysComponents'), + }, + { + path: '/components/pageTable', + meta:{ + permission:[] + }, + component: r => require.ensure([], () => r(require('../page/components/function/pageTable')), 'sysComponents'), + }, + { + path: '/components/pageSearch', + meta:{ + permission:[] + }, + component: r => require.ensure([], () => r(require('../page/components/ui/pageSearch')), 'sysComponents'), + }, + { + path: '/components/pageSection', + meta:{ + permission:[] + }, + component: r => require.ensure([], () => r(require('../page/components/ui/pageSection')), 'sysComponents'), + }, + { + path: '/components/pageTitle', + meta:{ + permission:[] + }, + component: r => require.ensure([], () => r(require('../page/components/ui/pageTitle')), 'sysComponents'), + }, + { + path: '/components/pageToolbar', + meta:{ + permission:[] + }, + component: r => require.ensure([], () => r(require('../page/components/ui/pageToolbar')), 'sysComponents'), + }, + { + path: '/components/pageNotes', + meta:{ + permission:[] + }, + component: r => require.ensure([], () => r(require('../page/components/assist/pageNotes')), 'sysComponents'), + }, + { + path: '/example/table', + meta:{ + permission:[] + }, + component: r => require.ensure([], () => r(require('../page/example/table')), 'example'), + }, + { + path: '/example/charts', + meta:{ + permission:[] + }, + component: r => require.ensure([], () => r(require('../page/example/charts/charts')), 'example'), + }, + { + path: '/example/map', + meta:{ + permission:[] + }, + component: r => require.ensure([], () => r(require('../page/example/map/map')), 'example'), + }, + { + path: '/i18n', + meta:{ + permission:[] + }, + component: r => require.ensure([], () => r(require('../page/i18n/i18n')), 'i18n'), + }, + { + path: '/theme', + meta:{ + permission:[] + }, + component: r => require.ensure([], () => r(require('../page/themeChange/themeChange')), 'theme'), + } + +] + +export default asyncRouter diff --git a/src/router/directAccess.js b/src/router/directAccess.js new file mode 100644 index 0000000..8addceb --- /dev/null +++ b/src/router/directAccess.js @@ -0,0 +1,11 @@ +// 免登录白名单页面 +const whiteList = [ + '/login', + '/register', + // 系统通知/升级 + '/notice', + // 网站维护 + '/maintenance' +] + +export default whiteList \ No newline at end of file diff --git a/src/router/index.js b/src/router/index.js new file mode 100644 index 0000000..af13dca --- /dev/null +++ b/src/router/index.js @@ -0,0 +1,164 @@ +// 路由控制 +// { +// path: 路由地址, +// component: r => require.ensure([], () => r(require('路由页面')), '打包后的文件名'), +// } +import Vue from 'vue' +import VueRouter from 'vue-router' +import store from '../store' +import Cookies from 'js-cookie' +import NProgress from 'nprogress' +import 'nprogress/nprogress.css' +import whiteList from './directAccess' +import asyncRouter from './asyncRouter' + +// 页面刷新时,重新赋值token +if (Cookies.get('token')) { + store.dispatch('user/relogin') +} +NProgress.configure({ showSpinner: false }); +Vue.use(VueRouter) + +/** + * 根据权限匹配路由 + * @param {array} permission 权限列表(菜单列表) + * @param {array} asyncRouter 异步路由对象 + */ +function routerMatch(permission, asyncRouter){ + return new Promise((resolve) => { + const routers = asyncRouter[0] + // 创建路由 + function createRouter(permission){ + permission.forEach((item) => { + if(item.child && item.child.length){ + // 递归 + createRouter(item.child) + } + let path = item.path + // 循环异步路由,将符合权限列表的路由加入到routers中 + asyncRouter.find(function(s){ + if(s.path == path){ + s.meta.permission = item.permission + routers.children.push(s) + return + } + }) + }) + } + + createRouter(permission) + resolve([routers]) + }) +} + +// 默认路由表,不需要权限 +const routes = [{ + path: '/', + // 重定向 + redirect: '/home' + }, + { + path: '/login', + component: r => require.ensure([], () => r(require('../page/login/login')), 'login') + }, + { + path: '/defaultLayout', + component: r => require.ensure([], () => r(require('../page/layout/layout')), 'layout'), + meta:{ + permission:[] + }, + // 需要进行用户登录验证 + children: [{ + path: '/home', + component: r => require.ensure([], () => r(require('../page/home/home')), 'home'), + }] + }, + { + path: '/error', + component: r => require.ensure([], () => r(require('../page/error/error')), 'error'), + children: [ + { + path: '/error/401', + component: r => require.ensure([], () => r(require('../page/error/401')), 'error') + }, + { + path: '/error/403', + component: r => require.ensure([], () => r(require('../page/error/403')), 'error') + }, + { + path: '/error/404', + component: r => require.ensure([], () => r(require('../page/error/404')), 'error') + }, + { + path: '/error/500', + component: r => require.ensure([], () => r(require('../page/error/500')), 'error') + } + ] + } +] + + +const router = new VueRouter({ + mode: 'history', + routes: routes +}) + +// 路由跳转前验证 +router.beforeEach((to, from, next) => { + // 开启进度条 + NProgress.start(); + + // 判断用户是否登录 + if (Cookies.get('token')) { + // 如果当前处于登录状态,并且跳转地址为login,则自动跳回系统首页 + // 这种情况出现在手动修改地址栏地址时 + if (to.path === '/login') { + router.replace('/home') + } else { + // 页面跳转前先判断是否存在权限列表,如果存在则直接跳转,如果没有则请求一次 + if (store.state.permission.list.length === 0) { + // 获取权限列表,如果失败则跳回登录页重新登录 + store.dispatch('permission/getPermission').then(res => { + // 匹配并生成需要添加的路由对象 + routerMatch(res, asyncRouter).then(res => { + // console.log(res) + router.addRoutes(res) + next(to.path) + }) + }).catch(() => { + console.log('登录错误') + store.dispatch('user/logout').then(() => { + router.replace('/login') + }) + }) + } else { + // 如果跳转页面存在于路由中则进入,否则跳转到404 + // 因为可以通过改变url值进行访问,所以必须有该判断 + if(to.matched.length){ + if(whiteList.indexOf(to.path) < 0){ + // store.dispatch('user/actionlog', to) + } + next() + } else{ + router.replace('/error/404') + } + } + } + } else { + // 如果是免登陆的页面则直接进入,否则跳转到登录页面 + if (whiteList.indexOf(to.path) >= 0) { + console.log('该页面无需登录即可访问') + next() + } else { + console.log('请重新登录') + router.replace('/login') + NProgress.done() + } + } +}) + +router.afterEach(() => { + NProgress.done(); // 结束Progress +}) + +export default router \ No newline at end of file diff --git a/src/store/index.js b/src/store/index.js new file mode 100644 index 0000000..c3b9da0 --- /dev/null +++ b/src/store/index.js @@ -0,0 +1,13 @@ +import Vue from 'vue' +import Vuex from 'vuex' +import vuexModules from './modules' + +import state from './state' +import mutations from './mutations' + +Vue.use(Vuex) +export default new Vuex.Store({ + state, + mutations, + modules: vuexModules +}) \ No newline at end of file diff --git a/src/store/modules/index.js b/src/store/modules/index.js new file mode 100644 index 0000000..f21541a --- /dev/null +++ b/src/store/modules/index.js @@ -0,0 +1,7 @@ +import user from './user' +import permission from './permission' + +export default { + user: user, + permission: permission +} \ No newline at end of file diff --git a/src/store/modules/permission/index.js b/src/store/modules/permission/index.js new file mode 100644 index 0000000..aff6da1 --- /dev/null +++ b/src/store/modules/permission/index.js @@ -0,0 +1,50 @@ +import axios from '@/util/ajax' +// import { Message } from 'element-ui'; + +const state = { + // 权限获取方式: 每次跳页获取(pageChange),暂时无法实现,因router未提供覆盖事件 / 登录后一次性获取(login) default:login + mode: 'login', + // 完整权限列表(菜单列表) + list: [] +} + +const getters = {} + +const mutations = { + setMode: (state, data) => { + state.mode = data + }, + setList: (state, data) => { + state.list = data + } +} + +const actions = { + // 获取权限列表 + getPermission({commit, rootState}){ + return new Promise((resolve, reject) =>{ + let uid = rootState.uid + axios({ + url: '/user/navlist', + methods: 'post', + data: { + uid: uid + } + }).then((res) => { + // 存储权限列表 + commit('setList', res.data) + resolve(res.data) + }).catch(() => { + reject() + }) + }) + } +} + +export default { + namespaced: true, + state, + mutations, + actions, + getters +} \ No newline at end of file diff --git a/src/store/modules/user/index.js b/src/store/modules/user/index.js new file mode 100644 index 0000000..f8eed9d --- /dev/null +++ b/src/store/modules/user/index.js @@ -0,0 +1,117 @@ +import axios from '@/util/ajax' +import Cookies from 'js-cookie' +import { Message } from 'element-ui'; + +const state = { + // uid + uid: '', + // 用户名 + name: '', + // token + token: '', + // 角色分组 + role: '' + // 头像 + // avatar: '' +} + +const getters = {} + +const mutations = { + setUID: (state, data) => { + if(data){ + Cookies.set('uid', data) + } else { + Cookies.remove('uid') + } + state.uid = data + }, + setName: (state, data) => { + if(data){ + Cookies.set('name', encodeURIComponent(data)) + } else { + Cookies.remove('name') + } + state.name = data + }, + setToken: (state, data) => { + if(data){ + Cookies.set('token', data) + } else { + Cookies.remove('token') + } + state.token = data + }, + setRole: (state, data) => { + state.role = data + } +} + +const actions = { + // 邮箱登录 + loginByEmail({ commit, rootState }, userInfo) { + return new Promise((resolve, reject) => { + axios({ + url: '/login', + method: 'post', + data: { + ...userInfo + } + }).then(res => { + const data = res.data + if(data.login){ + commit('setUID', data.uid) + commit('setName', data.name) + commit('setToken', data.token) + Cookies.set('lang', rootState.lang) + } + resolve(res) + }).catch(err => { + reject(err.data.message) + }) + }); + }, + // 登出 + logout({commit}) { + return new Promise((resolve) => { + commit('setUID', '') + commit('setName', '') + commit('setToken', '') + resolve() + }) + }, + // 重新登录 + relogin({commit}){ + return new Promise((resolve) => { + // TODO 问题严重,重新登录需要字段不明,但肯定不能保存token + commit('setUID', Cookies.get('uid')) + commit('setName', decodeURIComponent(Cookies.get('name'))) + commit('setToken', Cookies.get('token')) + resolve() + }) + }, + // 记录操作日志 + actionlog(data){ + axios({ + url: '/actionlog', + method: 'post', + data: { + 'uid': state.uid, + 'path': data.path + } + }).catch(() => { + Message({ + message: '保存操作记录失败', + type: 'error' + }) + }) + } +} + +export default { + namespaced: true, + state, + getters, + mutations, + actions +} \ No newline at end of file diff --git a/src/store/mutations.js b/src/store/mutations.js new file mode 100644 index 0000000..8d1ffb3 --- /dev/null +++ b/src/store/mutations.js @@ -0,0 +1,21 @@ +import Cookies from 'js-cookie' +import i18n from '@/util/i18n' + +export default { + changeLang(state, data){ + if(data){ + Cookies.set('lang', data) + i18n.locale = data + state.lang = data + } else{ + + } + }, + changeLayout(state, data){ + if(data){ + state.navbarPosition = data + } else{ + console.error("改变语言环境错误:必须传入需要改变的语言代码。") + } + } +} \ No newline at end of file diff --git a/src/store/state.js b/src/store/state.js new file mode 100644 index 0000000..19b082a --- /dev/null +++ b/src/store/state.js @@ -0,0 +1,14 @@ +import i18n from '@/util/i18n' + +let lang = i18n.locale + +export default { + // 当前语言模式 zh / en + lang: lang, + // 导航条位置 left / top + navbarPosition: 'left', + // 当前系统主题 default / BBA / darkBlue + theme: 'default', + // 通知框等需要自动消失的时间 + duration: 5000 +} \ No newline at end of file diff --git a/src/util/Cookie.js b/src/util/Cookie.js new file mode 100644 index 0000000..5c68c60 --- /dev/null +++ b/src/util/Cookie.js @@ -0,0 +1,41 @@ +export default { + /** + * 设置cookie + * @param {string} key + * @param {string|number} value + * @param {number} day + */ + set(key, value, day) { + let Days = day ? day : 30, + exp = new Date(); + exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000); + document.cookie = name + "=" + escape(value) + ";expires=" + exp.toGMTString(); + }, + /** + * 获取cookie + * @param {string} name + * @returns + */ + get(name) { + let arr, + reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)"); + + if (arr = document.cookie.match(reg)){ + return unescape(arr[2]); + } else { + return null; + } + }, + /** + * 删除cookie + * @param {string} name + */ + del(name) { + let exp = new Date(), + cval = getCookie(name); + exp.setTime(exp.getTime() - 1); + if (cval != null) { + document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString(); + } + } +} \ No newline at end of file diff --git a/src/util/ajax.js b/src/util/ajax.js new file mode 100644 index 0000000..c69b644 --- /dev/null +++ b/src/util/ajax.js @@ -0,0 +1,46 @@ +/** + * axios全局配置,包括验证校验及错误处理 + */ +import axios from 'axios' +import store from '../store' +import router from '../router' + +// 超时设置 +const service = axios.create({ + timeout: 5000 // 请求超时时间 +}); +// baseURL +// axios.defaults.baseURL = 'https://api.github.com'; + +// http request 拦截器 +// 每次请求都为http头增加Authorization字段,其内容为token +service.interceptors.request.use( + config => { + if (store.state.user.token) { + config.headers.Authorization = `token ${store.state.user.token}`; + } + return config; + }, + err => { + return Promise.reject(err); + }); + +// http response 拦截器 +// 针对响应代码确认跳转到对应页面 +service.interceptors.response.use( + response => response, + error => { + if (error.response) { + switch (error.response.status) { + case 401: + router.push('error/401'); + case 403: + router.push('error/403'); + } + } + // // console.log(JSON.stringify(error));//console : Error: Request failed with status code 402 + return Promise.reject(error.response.data) + } +); + +export default service; \ No newline at end of file diff --git a/src/util/amap.js b/src/util/amap.js new file mode 100644 index 0000000..be1428f --- /dev/null +++ b/src/util/amap.js @@ -0,0 +1,22 @@ +export default { + load(callback){ + if (window.AMap){ + callback() + } else{ + // 载入高德地图和UI组件 + var script = document.createElement('script') + script.type = 'text/javascript' + script.async = true + script.src = 'https://webapi.amap.com/maps?v=1.4.1&key=4e4c8706ad7f1d468011d7b1d2340bf2&callback=initAmap' + document.body.appendChild(script) + window.initAmap = () =>{ + callback() + } + } + }, + defaultOption: { + center: [116.397428, 39.90923], + resizeEnable: true, + zoom: 10 + } +} \ No newline at end of file diff --git a/src/util/echarts.theme.default.js b/src/util/echarts.theme.default.js new file mode 100644 index 0000000..292e972 --- /dev/null +++ b/src/util/echarts.theme.default.js @@ -0,0 +1,496 @@ +import echarts from 'echarts' + +echarts.registerTheme('westeros', { + "color": [ + "#516b91", + "#59c4e6", + "#edafda", + "#93b7e3", + "#a5e7f0", + "#cbb0e3" + ], + "backgroundColor": "rgba(0,0,0,0)", + "textStyle": {}, + "title": { + "textStyle": { + "color": "#516b91" + }, + "subtextStyle": { + "color": "#93b7e3" + } + }, + "line": { + "itemStyle": { + "normal": { + "borderWidth": "2" + } + }, + "lineStyle": { + "normal": { + "width": "2" + } + }, + "symbolSize": "6", + "symbol": "emptyCircle", + "smooth": true + }, + "radar": { + "itemStyle": { + "normal": { + "borderWidth": "2" + } + }, + "lineStyle": { + "normal": { + "width": "2" + } + }, + "symbolSize": "6", + "symbol": "emptyCircle", + "smooth": true + }, + "bar": { + "itemStyle": { + "normal": { + "barBorderWidth": 0, + "barBorderColor": "#ccc" + }, + "emphasis": { + "barBorderWidth": 0, + "barBorderColor": "#ccc" + } + } + }, + "pie": { + "itemStyle": { + "normal": { + "borderWidth": 0, + "borderColor": "#ccc" + }, + "emphasis": { + "borderWidth": 0, + "borderColor": "#ccc" + } + } + }, + "scatter": { + "itemStyle": { + "normal": { + "borderWidth": 0, + "borderColor": "#ccc" + }, + "emphasis": { + "borderWidth": 0, + "borderColor": "#ccc" + } + } + }, + "boxplot": { + "itemStyle": { + "normal": { + "borderWidth": 0, + "borderColor": "#ccc" + }, + "emphasis": { + "borderWidth": 0, + "borderColor": "#ccc" + } + } + }, + "parallel": { + "itemStyle": { + "normal": { + "borderWidth": 0, + "borderColor": "#ccc" + }, + "emphasis": { + "borderWidth": 0, + "borderColor": "#ccc" + } + } + }, + "sankey": { + "itemStyle": { + "normal": { + "borderWidth": 0, + "borderColor": "#ccc" + }, + "emphasis": { + "borderWidth": 0, + "borderColor": "#ccc" + } + } + }, + "funnel": { + "itemStyle": { + "normal": { + "borderWidth": 0, + "borderColor": "#ccc" + }, + "emphasis": { + "borderWidth": 0, + "borderColor": "#ccc" + } + } + }, + "gauge": { + "itemStyle": { + "normal": { + "borderWidth": 0, + "borderColor": "#ccc" + }, + "emphasis": { + "borderWidth": 0, + "borderColor": "#ccc" + } + } + }, + "candlestick": { + "itemStyle": { + "normal": { + "color": "#edafda", + "color0": "transparent", + "borderColor": "#d680bc", + "borderColor0": "#8fd3e8", + "borderWidth": "2" + } + } + }, + "graph": { + "itemStyle": { + "normal": { + "borderWidth": 0, + "borderColor": "#ccc" + } + }, + "lineStyle": { + "normal": { + "width": 1, + "color": "#aaa" + } + }, + "symbolSize": "6", + "symbol": "emptyCircle", + "smooth": true, + "color": [ + "#516b91", + "#59c4e6", + "#edafda", + "#93b7e3", + "#a5e7f0", + "#cbb0e3" + ], + "label": { + "normal": { + "textStyle": { + "color": "#eee" + } + } + } + }, + "map": { + "itemStyle": { + "normal": { + "areaColor": "#f3f3f3", + "borderColor": "#516b91", + "borderWidth": 0.5 + }, + "emphasis": { + "areaColor": "rgba(165,231,240,1)", + "borderColor": "#516b91", + "borderWidth": 1 + } + }, + "label": { + "normal": { + "textStyle": { + "color": "#000" + } + }, + "emphasis": { + "textStyle": { + "color": "rgb(81,107,145)" + } + } + } + }, + "geo": { + "itemStyle": { + "normal": { + "areaColor": "#f3f3f3", + "borderColor": "#516b91", + "borderWidth": 0.5 + }, + "emphasis": { + "areaColor": "rgba(165,231,240,1)", + "borderColor": "#516b91", + "borderWidth": 1 + } + }, + "label": { + "normal": { + "textStyle": { + "color": "#000" + } + }, + "emphasis": { + "textStyle": { + "color": "rgb(81,107,145)" + } + } + } + }, + "categoryAxis": { + "axisLine": { + "show": true, + "lineStyle": { + "color": "#cccccc" + } + }, + "axisTick": { + "show": false, + "lineStyle": { + "color": "#333" + } + }, + "axisLabel": { + "show": true, + "textStyle": { + "color": "#999999" + } + }, + "splitLine": { + "show": true, + "lineStyle": { + "color": [ + "#eeeeee" + ] + } + }, + "splitArea": { + "show": false, + "areaStyle": { + "color": [ + "rgba(250,250,250,0.05)", + "rgba(200,200,200,0.02)" + ] + } + } + }, + "valueAxis": { + "axisLine": { + "show": true, + "lineStyle": { + "color": "#cccccc" + } + }, + "axisTick": { + "show": false, + "lineStyle": { + "color": "#333" + } + }, + "axisLabel": { + "show": true, + "textStyle": { + "color": "#999999" + } + }, + "splitLine": { + "show": true, + "lineStyle": { + "color": [ + "#eeeeee" + ] + } + }, + "splitArea": { + "show": false, + "areaStyle": { + "color": [ + "rgba(250,250,250,0.05)", + "rgba(200,200,200,0.02)" + ] + } + } + }, + "logAxis": { + "axisLine": { + "show": true, + "lineStyle": { + "color": "#cccccc" + } + }, + "axisTick": { + "show": false, + "lineStyle": { + "color": "#333" + } + }, + "axisLabel": { + "show": true, + "textStyle": { + "color": "#999999" + } + }, + "splitLine": { + "show": true, + "lineStyle": { + "color": [ + "#eeeeee" + ] + } + }, + "splitArea": { + "show": false, + "areaStyle": { + "color": [ + "rgba(250,250,250,0.05)", + "rgba(200,200,200,0.02)" + ] + } + } + }, + "timeAxis": { + "axisLine": { + "show": true, + "lineStyle": { + "color": "#cccccc" + } + }, + "axisTick": { + "show": false, + "lineStyle": { + "color": "#333" + } + }, + "axisLabel": { + "show": true, + "textStyle": { + "color": "#999999" + } + }, + "splitLine": { + "show": true, + "lineStyle": { + "color": [ + "#eeeeee" + ] + } + }, + "splitArea": { + "show": false, + "areaStyle": { + "color": [ + "rgba(250,250,250,0.05)", + "rgba(200,200,200,0.02)" + ] + } + } + }, + "toolbox": { + "iconStyle": { + "normal": { + "borderColor": "#999" + }, + "emphasis": { + "borderColor": "#666" + } + } + }, + "legend": { + "textStyle": { + "color": "#999999" + } + }, + "tooltip": { + "axisPointer": { + "lineStyle": { + "color": "#ccc", + "width": 1 + }, + "crossStyle": { + "color": "#ccc", + "width": 1 + } + } + }, + "timeline": { + "lineStyle": { + "color": "#8fd3e8", + "width": 1 + }, + "itemStyle": { + "normal": { + "color": "#8fd3e8", + "borderWidth": 1 + }, + "emphasis": { + "color": "#8fd3e8" + } + }, + "controlStyle": { + "normal": { + "color": "#8fd3e8", + "borderColor": "#8fd3e8", + "borderWidth": 0.5 + }, + "emphasis": { + "color": "#8fd3e8", + "borderColor": "#8fd3e8", + "borderWidth": 0.5 + } + }, + "checkpointStyle": { + "color": "#8fd3e8", + "borderColor": "rgba(138,124,168,0.37)" + }, + "label": { + "normal": { + "textStyle": { + "color": "#8fd3e8" + } + }, + "emphasis": { + "textStyle": { + "color": "#8fd3e8" + } + } + } + }, + "visualMap": { + "color": [ + "#516b91", + "#59c4e6", + "#a5e7f0" + ] + }, + "dataZoom": { + "backgroundColor": "rgba(0,0,0,0)", + "dataBackgroundColor": "rgba(255,255,255,0.3)", + "fillerColor": "rgba(167,183,204,0.4)", + "handleColor": "#a7b7cc", + "handleSize": "100%", + "textStyle": { + "color": "#333" + } + }, + "markPoint": { + "label": { + "normal": { + "textStyle": { + "color": "#eee" + } + }, + "emphasis": { + "textStyle": { + "color": "#eee" + } + } + } + } +}); + + + +export default echarts \ No newline at end of file diff --git a/src/util/i18n.js b/src/util/i18n.js new file mode 100644 index 0000000..3cf24e7 --- /dev/null +++ b/src/util/i18n.js @@ -0,0 +1,41 @@ +// 国际化设置 +import Vue from 'vue'; +import VueI18n from 'vue-i18n' + +import ElementUI from 'element-ui' +import enElement from 'element-ui/lib/locale/lang/en' +import zhElement from 'element-ui/lib/locale/lang/zh-CN' +import enLocale from '@/lang/en' +import zhLocale from '@/lang/zh-cn' + +const messages = { + en: { + global: { + ...enLocale + }, + ...enElement + }, + zh: { + global: { + ...zhLocale + }, + ...zhElement + } +} + + +Vue.use(VueI18n) + +const i18n = new VueI18n({ + // 当前语言环境 + locale: 'zh', + // 默认语言环境。如果locale中无匹配项则采用该项值 + fallbackLocale: 'zh', + messages +}) + +Vue.use(ElementUI, { + i18n: (key, value) => i18n.t(key, value) +}) + +export default i18n \ No newline at end of file diff --git a/static/.gitkeep b/static/.gitkeep new file mode 100644 index 0000000..e69de29