diff --git a/.gitignore b/.gitignore index a5060b02..bb2a167e 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ test/unit/coverage test/e2e/reports selenium-debug.log .idea +package-lock.json diff --git a/.postcssrc.js b/.postcssrc.js index ea9a5ab8..09948d63 100644 --- a/.postcssrc.js +++ b/.postcssrc.js @@ -2,7 +2,7 @@ module.exports = { "plugins": { - // to edit target browsers: use "browserlist" field in package.json + // to edit target browsers: use "browserslist" field in package.json "autoprefixer": {} } } diff --git a/README-en.md b/README-en.md index 39d4c892..25459147 100644 --- a/README-en.md +++ b/README-en.md @@ -32,8 +32,9 @@ - ECharts - 401, 404 error page - Error log -- Exporting to Excel +- Export Excel - Upload Excel +- Export Zip - Table example - Interactive table example - Drag & drop table example @@ -47,6 +48,7 @@ - screenfull - markdown2html - views-tab +- clipboard ## Development diff --git a/README.md b/README.md index 34e78b92..34102b0c 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,8 @@ **注意:该项目目前使用element-ui@1.4.2版本,所以最低兼容 Vue 2.3.0** +楼主这里有一份调查[问卷](https://www.wjx.cn/m/16866569.aspx) 有空请填写一下,以表对本项目的支持~ps:不是给这个调查问卷网站做广告,所以填完问卷不用点上面抽奖有的没的那些东西 + ## 前言 > 这半年来一直在用vue写管理后台,目前后台已经有百来个页面,十几种权限,但维护成本依然很低,所以准备开源分享一下后台开发的经验和成果。目前的技术栈主要的采用vue+element+axios由webpack2打包。由于是个人项目,所以数据请求都是用了mockjs模拟。注意:在此项目基础上改造开发时请移除mock文件。 @@ -63,6 +65,7 @@ - 401,404错误页面 - 错误日志 - 导出excel +- zip - 前端可视化excel - table example - 动态table example @@ -78,6 +81,7 @@ - screenfull - markdown2html - views-tab +- clipboard ## 开发 diff --git a/build/build.js b/build/build.js index da9522a1..2041892b 100644 --- a/build/build.js +++ b/build/build.js @@ -9,9 +9,7 @@ var webpack = require('webpack'); var config = require('../config'); var webpackConfig = require('./webpack.prod.conf'); -console.log(process.env.NODE_ENV) - -var spinner = ora('building for ' + process.env.NODE_ENV + '...') +var spinner = ora('building for ' + process.env.NODE_ENV + ' of ' + process.env.env_config+ ' mode...' ) spinner.start() diff --git a/build/dev-server.js b/build/dev-server.js index 34c32b3c..254a3bb1 100644 --- a/build/dev-server.js +++ b/build/dev-server.js @@ -1,4 +1,5 @@ require('./check-versions')(); // 检查 Node 和 npm 版本 + var config = require('../config'); if (!process.env.NODE_ENV) { process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV) @@ -28,8 +29,8 @@ var devMiddleware = require('webpack-dev-middleware')(compiler, { }); var hotMiddleware = require('webpack-hot-middleware')(compiler, { - log: () => { - } + log: false, + heartbeat: 2000 }); // force page reload when html-webpack-plugin template changes @@ -40,8 +41,6 @@ compiler.plugin('compilation', function (compilation) { }) }); -// compiler.apply(new DashboardPlugin()); - // proxy api requests Object.keys(proxyTable).forEach(function (context) { var options = proxyTable[context] @@ -67,18 +66,26 @@ app.use(staticPath, express.static('./static')); var uri = 'http://localhost:' + port -devMiddleware.waitUntilValid(function () { - console.log('> Listening at ' + uri + '\n') -}); +var _resolve +var readyPromise = new Promise(resolve => { + _resolve = resolve +}) -module.exports = app.listen(port, function (err) { - if (err) { - console.log(err); - return - } +console.log('> Starting dev server...') +devMiddleware.waitUntilValid(() => { + console.log('> Listening at ' + uri + '\n') + // when env is testing, don't need open it + if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') { + opn(uri) + } + _resolve() +}) - // when env is testing, don't need open it - if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') { - opn(uri) - } -}); +var server = app.listen(port) + +module.exports = { + ready: readyPromise, + close: () => { + server.close() + } +} diff --git a/build/webpack.base.conf.js b/build/webpack.base.conf.js index d82a880c..0fd53f61 100644 --- a/build/webpack.base.conf.js +++ b/build/webpack.base.conf.js @@ -14,7 +14,7 @@ module.exports = { output: { path: config.build.assetsRoot, filename: '[name].js', - publicPath: process.env.NODE_ENV !== 'development' ? config.build.assetsPublicPath : config.dev.assetsPublicPath + publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath }, resolve: { extensions: ['.js', '.vue', '.json'], @@ -38,13 +38,13 @@ module.exports = { module: { rules: [ { - test: /\.(js|vue)$/, - loader: 'eslint-loader', - enforce: "pre", - include: [resolve('src'), resolve('test')], - options: { - formatter: require('eslint-friendly-formatter') - } + test: /\.(js|vue)$/, + loader: 'eslint-loader', + enforce: "pre", + include: [resolve('src'), resolve('test')], + options: { + formatter: require('eslint-friendly-formatter') + } }, { test: /\.vue$/, diff --git a/build/webpack.prod.conf.js b/build/webpack.prod.conf.js index 05f84874..cf50e0c9 100644 --- a/build/webpack.prod.conf.js +++ b/build/webpack.prod.conf.js @@ -9,7 +9,7 @@ var HtmlWebpackPlugin = require('html-webpack-plugin') var ExtractTextPlugin = require('extract-text-webpack-plugin') var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') -var env = process.env.NODE_ENV === 'production' ? config.build.prodEnv : config.build.sitEnv +var env = config.build[process.env.env_config+'Env'] function resolveApp(relativePath) { return path.resolve(relativePath); @@ -95,6 +95,14 @@ var webpackConfig = merge(baseWebpackConfig, { return context && (context.indexOf('echarts') >= 0 || context.indexOf('zrender') >= 0); } }), + // split xlsx into its own file + new webpack.optimize.CommonsChunkPlugin({ + async: 'xlsx', + minChunks(module) { + var context = module.context; + return context && (context.indexOf('xlsx') >= 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({ @@ -109,9 +117,11 @@ var webpackConfig = merge(baseWebpackConfig, { }]) ] }) + if (config.build.bundleAnalyzerReport) { var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin webpackConfig.plugins.push(new BundleAnalyzerPlugin()) } + module.exports = webpackConfig diff --git a/config/dev.env.js b/config/dev.env.js index e26486cd..f4aeda50 100644 --- a/config/dev.env.js +++ b/config/dev.env.js @@ -1,5 +1,6 @@ module.exports = { NODE_ENV: '"development"', + ENV_CONFIG: '"dev"', BASE_API: '"https://api-dev"', APP_ORIGIN: '"https://wallstreetcn.com"' } diff --git a/config/index.js b/config/index.js index 581d53a3..c38e0b84 100644 --- a/config/index.js +++ b/config/index.js @@ -3,37 +3,37 @@ var path = require('path') module.exports = { build: { - sitEnv: require('./sit.env'), - prodEnv: 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 + sitEnv: require('./sit.env'), + prodEnv: 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: 9527, - 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 + env: require('./dev.env'), + port: 9527, + 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 } } diff --git a/config/prod.env.js b/config/prod.env.js index cc935b9a..511b341a 100644 --- a/config/prod.env.js +++ b/config/prod.env.js @@ -1,5 +1,6 @@ module.exports = { NODE_ENV: '"production"', + ENV_CONFIG: '"prod"', BASE_API: '"https://api-prod"', APP_ORIGIN: '"https://wallstreetcn.com"' }; diff --git a/config/sit.env.js b/config/sit.env.js index 64cf403b..a9a041af 100644 --- a/config/sit.env.js +++ b/config/sit.env.js @@ -1,5 +1,6 @@ module.exports = { NODE_ENV: '"production"', + ENV_CONFIG: '"sit"', BASE_API: '"https://api-sit"', APP_ORIGIN: '"https://wallstreetcn.com"' }; diff --git a/package.json b/package.json index ae01ad50..2723c6a4 100644 --- a/package.json +++ b/package.json @@ -1,22 +1,23 @@ { "name": "juicy", - "version": "2.1.0", + "version": "2.2.1", "description": "A Vue.js admin", "author": "Pan ", "license": "MIT", "private": true, "scripts": { "dev": "node build/dev-server.js", - "build:prod": "cross-env NODE_ENV=production node build/build.js", - "build:sit": "cross-env NODE_ENV=sit node build/build.js", - "build:sit-preview": "cross-env NODE_ENV=sit npm_config_preview=true npm_config_report=true node build/build.js", + "build:prod": "cross-env NODE_ENV=production env_config=prod node build/build.js", + "build:sit": "cross-env NODE_ENV=production env_config=sit node build/build.js", + "build:sit-preview": "cross-env NODE_ENV=production env_config=sit npm_config_preview=true npm_config_report=true node build/build.js", "lint": "eslint --ext .js,.vue src" }, "dependencies": { "axios": "0.16.2", + "clipboard": "1.7.1", "codemirror": "5.26.0", "dropzone": "5.1.0", - "echarts": "3.6.2", + "echarts": "3.8.2", "element-ui": "1.4.2", "file-saver": "1.3.3", "js-cookie": "2.1.4", @@ -35,7 +36,8 @@ "vue-splitpane": "^1.0.0", "vuedraggable": "2.14.1", "vuex": "2.3.1", - "xlsx": "^0.10.8" + "xlsx": "^0.10.8", + "jszip": "^3.1.4" }, "devDependencies": { "autoprefixer": "7.1.1", @@ -90,7 +92,7 @@ "node": ">= 4.0.0", "npm": ">= 3.0.0" }, - "browserlist": [ + "browserslist": [ "> 1%", "last 2 versions", "not ie <= 8" diff --git a/src/components/MDinput/index.vue b/src/components/MDinput/index.vue index 72658598..6d9d5e8e 100644 --- a/src/components/MDinput/index.vue +++ b/src/components/MDinput/index.vue @@ -1,297 +1,272 @@ diff --git a/src/components/Tinymce/index.vue b/src/components/Tinymce/index.vue index 0dd164b3..ef9be84f 100644 --- a/src/components/Tinymce/index.vue +++ b/src/components/Tinymce/index.vue @@ -150,6 +150,12 @@ export default { }) }, methods: { + setContent(value) { + window.tinymce.get(this.tinymceId).setContent(value) + }, + getContent() { + window.tinymce.get(this.tinymceId).getContent() + }, imageSuccessCBK(arr) { const _this = this arr.forEach(v => { diff --git a/src/directive/clipboard/clipboard.js b/src/directive/clipboard/clipboard.js new file mode 100644 index 00000000..49c9b391 --- /dev/null +++ b/src/directive/clipboard/clipboard.js @@ -0,0 +1,49 @@ +// Inspired by https://github.com/Inndy/vue-clipboard2 +const Clipboard = require('clipboard') +if (!Clipboard) { + throw new Error('you shold npm install `clipboard` --save at first ') +} + +export default { + bind(el, binding) { + if (binding.arg === 'success') { + el._v_clipboard_success = binding.value + } else if (binding.arg === 'error') { + el._v_clipboard_error = binding.value + } else { + const clipboard = new Clipboard(el, { + text() { return binding.value }, + action() { return binding.arg === 'cut' ? 'cut' : 'copy' } + }) + clipboard.on('success', e => { + const callback = el._v_clipboard_success + callback && callback(e) // eslint-disable-line + }) + clipboard.on('error', e => { + const callback = el._v_clipboard_error + callback && callback(e) // eslint-disable-line + }) + el._v_clipboard = clipboard + } + }, + update(el, binding) { + if (binding.arg === 'success') { + el._v_clipboard_success = binding.value + } else if (binding.arg === 'error') { + el._v_clipboard_error = binding.value + } else { + el._v_clipboard.text = function() { return binding.value } + el._v_clipboard.action = function() { return binding.arg === 'cut' ? 'cut' : 'copy' } + } + }, + unbind(el, binding) { + if (binding.arg === 'success') { + delete el._v_clipboard_success + } else if (binding.arg === 'error') { + delete el._v_clipboard_error + } else { + el._v_clipboard.destroy() + delete el._v_clipboard + } + } +} diff --git a/src/directive/clipboard/index.js b/src/directive/clipboard/index.js new file mode 100644 index 00000000..02c98163 --- /dev/null +++ b/src/directive/clipboard/index.js @@ -0,0 +1,13 @@ +import Clipboard from './clipboard' + +const install = function(Vue) { + Vue.directive('Clipboard', Clipboard) +} + +if (window.Vue) { + window.clipboard = Clipboard + Vue.use(install); // eslint-disable-line +} + +Clipboard.install = install +export default Clipboard diff --git a/src/directive/waves/index.js b/src/directive/waves/index.js new file mode 100644 index 00000000..65f9b308 --- /dev/null +++ b/src/directive/waves/index.js @@ -0,0 +1,13 @@ +import waves from './waves' + +const install = function(Vue) { + Vue.directive('waves', waves) +} + +if (window.Vue) { + window.waves = waves + Vue.use(install); // eslint-disable-line +} + +waves.install = install +export default waves diff --git a/src/directive/waves.css b/src/directive/waves/waves.css similarity index 100% rename from src/directive/waves.css rename to src/directive/waves/waves.css diff --git a/src/directive/waves.js b/src/directive/waves/waves.js similarity index 100% rename from src/directive/waves.js rename to src/directive/waves/waves.js diff --git a/src/icons/svg/tubiao.svg b/src/icons/svg/chart.svg similarity index 100% rename from src/icons/svg/tubiao.svg rename to src/icons/svg/chart.svg diff --git a/src/icons/svg/clipboard.svg b/src/icons/svg/clipboard.svg new file mode 100644 index 00000000..cf1c9b0c --- /dev/null +++ b/src/icons/svg/clipboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/component.svg b/src/icons/svg/component.svg new file mode 100644 index 00000000..a8008c84 --- /dev/null +++ b/src/icons/svg/component.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/tuozhuai.svg b/src/icons/svg/drag.svg similarity index 100% rename from src/icons/svg/tuozhuai.svg rename to src/icons/svg/drag.svg diff --git a/src/icons/svg/zonghe.svg b/src/icons/svg/example.svg similarity index 100% rename from src/icons/svg/zonghe.svg rename to src/icons/svg/example.svg diff --git a/src/icons/svg/EXCEL.svg b/src/icons/svg/excel.svg similarity index 100% rename from src/icons/svg/EXCEL.svg rename to src/icons/svg/excel.svg diff --git a/src/icons/svg/yanjing.svg b/src/icons/svg/eye.svg similarity index 100% rename from src/icons/svg/yanjing.svg rename to src/icons/svg/eye.svg diff --git a/src/icons/svg/form.svg b/src/icons/svg/form.svg new file mode 100644 index 00000000..79716f06 --- /dev/null +++ b/src/icons/svg/form.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/from.svg b/src/icons/svg/from.svg deleted file mode 100644 index 7a4bd166..00000000 --- a/src/icons/svg/from.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/icons/svg/icons.svg b/src/icons/svg/icon.svg similarity index 100% rename from src/icons/svg/icons.svg rename to src/icons/svg/icon.svg diff --git a/src/icons/svg/quanxian.svg b/src/icons/svg/lock.svg similarity index 100% rename from src/icons/svg/quanxian.svg rename to src/icons/svg/lock.svg diff --git a/src/icons/svg/mima.svg b/src/icons/svg/password.svg similarity index 100% rename from src/icons/svg/mima.svg rename to src/icons/svg/password.svg diff --git a/src/icons/svg/xinrenzhinan.svg b/src/icons/svg/people.svg similarity index 100% rename from src/icons/svg/xinrenzhinan.svg rename to src/icons/svg/people.svg diff --git a/src/icons/svg/QQ.svg b/src/icons/svg/qq.svg similarity index 100% rename from src/icons/svg/QQ.svg rename to src/icons/svg/qq.svg diff --git a/src/icons/svg/shouce.svg b/src/icons/svg/shouce.svg deleted file mode 100644 index 94c68bb6..00000000 --- a/src/icons/svg/shouce.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/icons/svg/wujiaoxing.svg b/src/icons/svg/star.svg similarity index 100% rename from src/icons/svg/wujiaoxing.svg rename to src/icons/svg/star.svg diff --git a/src/icons/svg/tab.svg b/src/icons/svg/tab.svg index 657057df..17aa088b 100644 --- a/src/icons/svg/tab.svg +++ b/src/icons/svg/tab.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/icons/svg/a.svg b/src/icons/svg/trendChart1.svg similarity index 100% rename from src/icons/svg/a.svg rename to src/icons/svg/trendChart1.svg diff --git a/src/icons/svg/b.svg b/src/icons/svg/trendChart2.svg similarity index 100% rename from src/icons/svg/b.svg rename to src/icons/svg/trendChart2.svg diff --git a/src/icons/svg/c.svg b/src/icons/svg/trendChart3.svg similarity index 100% rename from src/icons/svg/c.svg rename to src/icons/svg/trendChart3.svg diff --git a/src/icons/svg/yonghuming.svg b/src/icons/svg/user.svg similarity index 100% rename from src/icons/svg/yonghuming.svg rename to src/icons/svg/user.svg diff --git a/src/icons/svg/weixin.svg b/src/icons/svg/wechat.svg similarity index 100% rename from src/icons/svg/weixin.svg rename to src/icons/svg/wechat.svg diff --git a/src/icons/svg/zip.svg b/src/icons/svg/zip.svg new file mode 100644 index 00000000..e9a9d012 --- /dev/null +++ b/src/icons/svg/zip.svg @@ -0,0 +1 @@ + diff --git a/src/icons/svg/zujian.svg b/src/icons/svg/zujian.svg deleted file mode 100644 index d183e56c..00000000 --- a/src/icons/svg/zujian.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/mock/login.js b/src/mock/login.js index 00ce9bde..5b00b503 100644 --- a/src/mock/login.js +++ b/src/mock/login.js @@ -34,7 +34,7 @@ export default { if (userMap[token]) { return userMap[token] } else { - return Promise.reject('error') + return false } }, logout: () => 'success' diff --git a/src/permission.js b/src/permission.js index 1070700a..2fcc4c9c 100644 --- a/src/permission.js +++ b/src/permission.js @@ -3,6 +3,7 @@ import store from './store' import NProgress from 'nprogress' // Progress 进度条 import 'nprogress/nprogress.css'// Progress 进度条样式 import { getToken } from '@/utils/auth' // 验权 +import { Message } from 'element-ui' // permissiom judge function hasPermission(roles, permissionRoles) { @@ -18,6 +19,7 @@ router.beforeEach((to, from, next) => { if (getToken()) { // 判断是否有token if (to.path === '/login') { next({ path: '/' }) + NProgress.done() // router在hash模式下 手动改变hash 重定向回来 不会触发afterEach 暂时hack方案 ps:history模式下无问题,可删除该行! } else { if (store.getters.roles.length === 0) { // 判断当前用户是否已拉取完user_info信息 store.dispatch('GetUserInfo').then(res => { // 拉取user_info @@ -28,6 +30,7 @@ router.beforeEach((to, from, next) => { }) }).catch(() => { store.dispatch('FedLogOut').then(() => { + Message.error('验证失败,请重新登录') next({ path: '/login' }) }) }) @@ -37,6 +40,7 @@ router.beforeEach((to, from, next) => { next()// } else { next({ path: '/401', query: { noGoBack: true }}) + NProgress.done() // router在hash模式下 手动改变hash 重定向回来 不会触发afterEach 暂时hack方案 ps:history模式下无问题,可删除该行! } // 可删 ↑ } @@ -46,7 +50,7 @@ router.beforeEach((to, from, next) => { next() } else { next('/login') // 否则全部重定向到登录页 - NProgress.done() // 在hash模式下 改变手动改变hash 重定向回来 不会触发afterEach 暂时hack方案 ps:history模式下无问题,可删除该行! + NProgress.done() // router在hash模式下 手动改变hash 重定向回来 不会触发afterEach 暂时hack方案 ps:history模式下无问题,可删除该行! } } }) diff --git a/src/router/index.js b/src/router/index.js index c235005a..a4cc7b9b 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -32,7 +32,7 @@ export const constantRouterMap = [ path: '/introduction', component: Layout, redirect: '/introduction/index', - icon: 'xinrenzhinan', + icon: 'people', noDropdown: true, children: [{ path: 'index', component: _import('introduction/index'), name: '简述' }] } @@ -50,7 +50,7 @@ export const asyncRouterMap = [ component: Layout, redirect: '/permission/index', name: '权限测试', - icon: 'quanxian', + icon: 'lock', meta: { role: ['admin'] }, noDropdown: true, children: [{ path: 'index', component: _import('permission/index'), name: '权限测试页', meta: { role: ['admin'] }}] @@ -58,7 +58,7 @@ export const asyncRouterMap = [ { path: '/icon', component: Layout, - icon: 'icons', + icon: 'icon', noDropdown: true, children: [{ path: 'index', component: _import('svg-icons/index'), name: 'icons' }] }, @@ -67,7 +67,7 @@ export const asyncRouterMap = [ component: Layout, redirect: '/components/index', name: '组件', - icon: 'zujian', + icon: 'component', children: [ { path: 'index', component: _import('components/index'), name: '介绍 ' }, { path: 'tinymce', component: _import('components/tinymce'), name: '富文本编辑器' }, @@ -88,7 +88,7 @@ export const asyncRouterMap = [ component: Layout, redirect: '/charts/index', name: '图表', - icon: 'tubiao', + icon: 'chart', children: [ { path: 'index', component: _import('charts/index'), name: '介绍' }, { path: 'keyboard', component: _import('charts/keyboard'), name: '键盘图表' }, @@ -102,7 +102,7 @@ export const asyncRouterMap = [ component: Layout, redirect: 'noredirect', name: '综合实例', - icon: 'zonghe', + icon: 'example', children: [ { path: '/example/table', @@ -117,8 +117,8 @@ export const asyncRouterMap = [ { path: 'table', component: _import('example/table/table'), name: '综合table' } ] }, - { path: 'form/edit', icon: 'shouce', component: _import('example/form'), name: '编辑Form', meta: { isEdit: true }}, - { path: 'form/create', icon: 'from', component: _import('example/form'), name: '创建Form' }, + { path: 'form/edit', icon: 'form', component: _import('example/form'), name: '编辑Form', meta: { isEdit: true }}, + { path: 'form/create', icon: 'form', component: _import('example/form'), name: '创建Form' }, { path: 'tab/index', icon: 'tab', component: _import('example/tab/index'), name: 'Tab' } ] }, @@ -147,13 +147,23 @@ export const asyncRouterMap = [ component: Layout, redirect: '/excel/download', name: 'excel', - icon: 'EXCEL', + icon: 'excel', children: [ - { path: 'download', component: _import('excel/index'), name: '导出excel' }, - { path: 'download2', component: _import('excel/selectExcel'), name: '导出已选择项' }, + { path: 'download', component: _import('excel/index'), name: 'export excel' }, + { path: 'download2', component: _import('excel/selectExcel'), name: 'export selected' }, { path: 'upload', component: _import('excel/uploadExcel'), name: 'upload excel' } ] }, + { + path: '/zip', + component: Layout, + redirect: '/zip/download', + name: 'zip', + icon: 'zip', + children: [ + { path: 'download', component: _import('zip/index'), name: 'export zip' } + ] + }, { path: '/theme', component: Layout, @@ -163,6 +173,14 @@ export const asyncRouterMap = [ noDropdown: true, children: [{ path: 'index', component: _import('theme/index'), name: '换肤' }] }, + { + path: '/clipboard', + component: Layout, + redirect: 'noredirect', + icon: 'clipboard', + noDropdown: true, + children: [{ path: 'index', component: _import('clipboard/index'), name: 'clipboard' }] + }, { path: '*', redirect: '/404', hidden: true } ] diff --git a/src/store/modules/user.js b/src/store/modules/user.js index 9c706978..0ac425e1 100644 --- a/src/store/modules/user.js +++ b/src/store/modules/user.js @@ -63,6 +63,9 @@ const user = { GetUserInfo({ commit, state }) { return new Promise((resolve, reject) => { getUserInfo(state.token).then(response => { + if (!response.data) { // 由于mockjs 不支持自定义状态码只能这样hack + reject('error') + } const data = response.data commit('SET_ROLES', data.role) commit('SET_NAME', data.name) diff --git a/src/utils/clipboard.js b/src/utils/clipboard.js new file mode 100644 index 00000000..882b1251 --- /dev/null +++ b/src/utils/clipboard.js @@ -0,0 +1,36 @@ +import Clipboard from 'clipboard' +import Vue from 'vue' + +function clipboardSuccess() { + Vue.prototype.$message({ + message: '复制成功', + type: 'success', + duration: 1500 + }) +} + +function clipboardError() { + Vue.prototype.$message({ + message: '复制失败', + type: 'error' + }) +} + +export default function handleClipboard(text, event) { + const clipboard = new Clipboard(event.target, { + text: () => text + }) + clipboard.on('success', () => { + clipboardSuccess() + clipboard.off('error') + clipboard.off('success') + clipboard.destroy() + }) + clipboard.on('error', () => { + clipboardError() + clipboard.off('error') + clipboard.off('success') + clipboard.destroy() + }) + clipboard.onClick(event) +} diff --git a/src/vendor/Export2Excel.js b/src/vendor/Export2Excel.js index a121a33a..4370da36 100644 --- a/src/vendor/Export2Excel.js +++ b/src/vendor/Export2Excel.js @@ -1,7 +1,8 @@ /* eslint-disable */ require('script-loader!file-saver'); require('script-loader!vendor/Blob'); -require('script-loader!xlsx/dist/xlsx.core.min'); +import XLSX from 'xlsx' + function generateArray(table) { var out = []; var rows = table.querySelectorAll('tr'); @@ -93,14 +94,12 @@ function s2ab(s) { export function export_table_to_excel(id) { var theTable = document.getElementById(id); - console.log('a') var oo = generateArray(theTable); var ranges = oo[1]; /* original data */ var data = oo[0]; var ws_name = "SheetJS"; - console.log(data); var wb = new Workbook(), ws = sheet_from_array_of_arrays(data); @@ -117,9 +116,6 @@ export function export_table_to_excel(id) { saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), "test.xlsx") } -function formatJson(jsonData) { - console.log(jsonData) -} export function export_json_to_excel(th, jsonData, defaultTitle) { /* original data */ @@ -130,6 +126,29 @@ export function export_json_to_excel(th, jsonData, defaultTitle) { var wb = new Workbook(), ws = sheet_from_array_of_arrays(data); + /*设置worksheet每列的最大宽度*/ + const colWidth = data.map(row => row.map(val => { + /*先判断是否为null/undefined*/ + if (val == null) { + return {'wch': 10}; + } + /*再判断是否为中文*/ + else if (val.toString().charCodeAt(0) > 255) { + return {'wch': val.toString().length * 2}; + } else { + return {'wch': val.toString().length}; + } + })) + /*以第一行为初始值*/ + let result = colWidth[0]; + for (let i = 1; i < colWidth.length; i++) { + for (let j = 0; j < colWidth[i].length; j++) { + if (result[j]['wch'] < colWidth[i][j]['wch']) { + result[j]['wch'] = colWidth[i][j]['wch']; + } + } + } + ws['!cols'] = result; /* add worksheet to workbook */ wb.SheetNames.push(ws_name); diff --git a/src/vendor/Export2Zip.js b/src/vendor/Export2Zip.js new file mode 100644 index 00000000..599eda18 --- /dev/null +++ b/src/vendor/Export2Zip.js @@ -0,0 +1,22 @@ +/* eslint-disable */ +require('script-loader!file-saver'); +import JSZip from 'jszip' + +export function export_txt_to_zip(th, jsonData, txtName, zipName) { + const zip = new JSZip() + const txt_name = txtName || '文本' + const zip_name = zipName || '压缩包' + const data = jsonData + let txtData = `${th}\r\n` + data.forEach((row) => { + let tempStr = '' + tempStr = row.toString() + txtData += `${tempStr}\r\n` + }) + zip.file(`${txt_name}.txt`, txtData) + zip.generateAsync({type:"blob"}).then((blob) => { + saveAs(blob, `${zip_name}.zip`) + }, (err) => { + alert('导出失败') + }) +} diff --git a/src/views/clipboard/index.vue b/src/views/clipboard/index.vue new file mode 100644 index 00000000..b0281abc --- /dev/null +++ b/src/views/clipboard/index.vue @@ -0,0 +1,44 @@ + + + + diff --git a/src/views/components/mixin.vue b/src/views/components/mixin.vue index f78ab1e0..5f450c91 100644 --- a/src/views/components/mixin.vue +++ b/src/views/components/mixin.vue @@ -1,9 +1,11 @@ diff --git a/src/views/zip/index.vue b/src/views/zip/index.vue new file mode 100644 index 00000000..fa32a983 --- /dev/null +++ b/src/views/zip/index.vue @@ -0,0 +1,74 @@ + + +