diff --git a/.babelrc b/.babelrc index 3a280ba3..6c0b7f27 100644 --- a/.babelrc +++ b/.babelrc @@ -8,5 +8,10 @@ }], "stage-2" ], - "plugins": ["transform-vue-jsx", "transform-runtime"] + "plugins": ["transform-vue-jsx", "transform-runtime"], + "env": { + "development":{ + "plugins": ["dynamic-import-node"] + } + } } diff --git a/.gitignore b/.gitignore index 49448d19..9322b8a6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,10 @@ .DS_Store node_modules/ dist/ -gifs/ npm-debug.log* yarn-debug.log* yarn-error.log* +**/*.log test/unit/coverage test/e2e/reports diff --git a/README.md b/README.md index 94768901..7dfa567d 100644 --- a/README.md +++ b/README.md @@ -3,52 +3,57 @@

- - vue - - - element-ui - - - Build Status - - - license - - - GitHub release - + + vue + + + element-ui + + + Build Status + + + license + + + GitHub release +

English | [简体中文](./README.zh-CN.md) ## Introduction -`vue-element-admin` is a production-ready solution for admin interfaces. Based on [Vue.js](https://github.com/vuejs/vue) and use the UI Toolkit -- [element](https://github.com/ElemeFE/element). `vue-element-admin` is a magical vue admin, it based on the newest development stack of vue, built-in i18n solution, typical templates for enterprise applications, lots of awesome features. It helps you build a large complex Single-Page Applications. I believe whatever your needs are, this project will help you. +[vue-element-admin](http://panjiachen.github.io/vue-element-admin) is a front-end management background integration solution. It based on [vue](https://github.com/vuejs/vue) and use the UI Toolkit [element](https://github.com/ElemeFE/element). + +It is a magical vue admin based on the newest development stack of vue, built-in i18n solution, typical templates for enterprise applications, lots of awesome features. It helps you build a large complex Single-Page Applications. I believe whatever your needs are, this project will help you. - [Preview](http://panjiachen.github.io/vue-element-admin) -- [Documentation](https://panjiachen.github.io/vue-element-admin-site/#/) +- [Documentation](https://panjiachen.github.io/vue-element-admin-site/) -- [wiki](https://github.com/PanJiaChen/vue-element-admin/wiki) +- [Gitter](https://gitter.im/vue-element-admin/discuss) -- [donate](https://panjiachen.github.io/vue-element-admin-site/#/donate) +- [Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki) -**vue-element-admin is a admin interfaces integration solution, which is not suitable for secondary development as a base template.** +- [Donate](https://panjiachen.github.io/vue-element-admin-site/donate/) + +- [Gitee](https://panjiachen.gitee.io/vue-element-admin/) 国内用户可访问该地址在线预览 + +**This project is positioned as a background integration solution and is not suitable for secondary development as a basic template.** - Base template recommends using: [vueAdmin-template](https://github.com/PanJiaChen/vueAdmin-template)   - Desktop: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin) -**Note: This project uses element-ui@2.0.0+ version, so the minimum compatible vue@2.5.0** - ## Preparation -You need to install [node](http://nodejs.org/) and [git](https://git-scm.com/) locally. The project is based on [ES2015+](http://es6.ruanyifeng.com/)、[vue](https://cn.vuejs.org/index.html)、[vuex](https://vuex.vuejs.org/zh-cn/)、[vue-router](https://router.vuejs.org/zh-cn/) 和 [element-ui](https://github.com/ElemeFE/element). All data requests for this project are simulated using [Mock.js](https://github.com/nuysoft/Mock). It would be helpful if you have pre-existing knowledge on those. - - **This project is not a scaffolding and is more of an integrated solution.** +You need to install [node](http://nodejs.org/) and [git](https://git-scm.com/) locally. The project is based on [ES2015+](http://es6.ruanyifeng.com/), [vue](https://cn.vuejs.org/index.html), [vuex](https://vuex.vuejs.org/zh-cn/), [vue-router](https://router.vuejs.org/zh-cn/), [axios](https://github.com/axios/axios) and [element-ui](https://github.com/ElemeFE/element), all request data is simulated using [Mock.js](https://github.com/nuysoft/Mock). + Understanding and learning this knowledge in advance will greatly help the use of this project. **This project does not support low version browsers (e.g. IE). Please add polyfill yourself if you need them.** + **Note: This project uses element-ui@2.3.0+ version, so the minimum compatible vue@2.5.0+** +

@@ -56,45 +61,71 @@ You need to install [node](http://nodejs.org/) and [git](https://git-scm.com/) l ## Features ``` - Login / Logout -- Permission authentication + +- Permission Authentication + - Page permission + - Directive permission + - Two-step login + - Multi-environment build -- Dynamic sidebar (supports multi-level routing) -- Dynamic breadcrumb -- I18n -- Customizable theme -- Tags-view(Tab page Support right-click operation) -- Rich text editor -- Markdown editor -- JSON editor -- Screenfull -- Drag and drop list -- Svg Sprite + - dev sit stage prod + +- Global Features + - I18n + - Multiple dynamic themes + - Dynamic sidebar (supports multi-level routing) + - Dynamic breadcrumb + - Tags-view(Tab page Support right-click operation) + - Svg Sprite + - Mock data + - Screenfull + - Responsive Sidebar + +- Editor + - Rich Text Editor + - Markdown Editor + - JSON Editor + +- Excel + - Export Excel + - Export zip + - Upload Excel + - Visualization Excel + +- Table + - Dynamic Table + - Drag And Drop Table + - Tree Table + - Inline Edit Table + +- Error Page + - 401 + - 404 + +- Components + - Avatar Upload + - Back To Top + - Drag Dialog + - Drag Kanban + - Drag List + - SplitPane + - Dropzone + - Sticky + - CountTo + +- Advanced Example +- Error Log - Dashboard -- Mock data +- Guide Page - Echarts - Clipboard -- 401/404 error page -- Error log -- Export excel -- Export zip -- Front-end visualization excel -- Table example -- Dynamictable example -- Drag and drop table example -- Inline edit table example -- Form example -- Two-step login -- SplitPane -- Dropzone -- Sticky -- CountTo - Markdown to html ``` ## Getting started ```bash -# clone the projice +# clone the project git clone https://github.com/PanJiaChen/vue-element-admin.git # install dependency @@ -130,7 +161,7 @@ npm run lint npm run lint -- --fix ``` -Refer to [Documentation](https://panjiachen.github.io/vue-element-admin-site/#/deploy) for more information +Refer to [Documentation](https://panjiachen.github.io/vue-element-admin-site/guide/essentials/deploy.html) for more information ## Changelog Detailed changes for each release are documented in the [release notes](https://github.com/PanJiaChen/vue-element-admin/releases). @@ -145,6 +176,8 @@ If you find this project useful, you can buy author a glass of juice :tropical_d [Paypal Me](https://www.paypal.me/panfree23) +[Buy me a coffee](https://www.buymeacoffee.com/Pan) + ## License [MIT](https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE) diff --git a/README.zh-CN.md b/README.zh-CN.md index ead8d63c..ef5251f5 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -3,46 +3,48 @@

- - vue - - - element-ui - - - Build Status - - - license - - - GitHub release - + + vue + + + element-ui + + + Build Status + + + license + + + GitHub release +

简体中文 | [English](./README.md) ## 简介 -`vue-element-admin` 是一个后台集成解决方案,它基于 [Vue.js](https://github.com/vuejs/vue) 和 [element](https://github.com/ElemeFE/element)。它使用了最新的前端技术栈,内置了i18国际化解决方案,动态路由,权限验证等很多功能特性,相信不管你的需求是什么,本项目都能帮助到你。 +[vue-element-admin](http://panjiachen.github.io/vue-element-admin) 是一个后台集成解决方案,它基于 [vue](https://github.com/vuejs/vue) 和 [element](https://github.com/ElemeFE/element)。它使用了最新的前端技术栈,内置了i18国际化解决方案,动态路由,权限验证,提炼了典型的业务模型,提供了丰富的功能组件,它可以帮助你快速搭建企业级中后台产品原型。相信不管你的需求是什么,本项目都能帮助到你。 - [在线访问](http://panjiachen.github.io/vue-element-admin) -- [使用文档](https://panjiachen.github.io/vue-element-admin-site/#/) +- [使用文档](https://panjiachen.github.io/vue-element-admin-site/zh/) -- [wiki](https://github.com/PanJiaChen/vue-element-admin/wiki) +- [Gitter讨论组](https://gitter.im/vue-element-admin/discuss) -- [donate](https://panjiachen.github.io/vue-element-admin-site/#/donate) +- [Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki) + +- [Donate](https://panjiachen.github.io/vue-element-admin-site/zh/donate/) + +- [Gitee](https://panjiachen.gitee.io/vue-element-admin/) 国内用户可访问该地址在线预览 **本项目的定位是后台集成方案,不适合当基础模板来开发。** - 模板建议使用: [vueAdmin-template](https://github.com/PanJiaChen/vueAdmin-template)   - 桌面端: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin) -**注意:该项目使用 element-ui@2.0.0+ 版本,所以最低兼容 vue@2.5.0** - ## 前序准备 -你的本地环境需要安装 [node](http://nodejs.org/) 和 [git](https://git-scm.com/)。我们的技术栈基于 [ES2015+](http://es6.ruanyifeng.com/)、[vue](https://cn.vuejs.org/index.html)、[vuex](https://vuex.vuejs.org/zh-cn/)、[vue-router](https://router.vuejs.org/zh-cn/) and [element-ui](https://github.com/ElemeFE/element),所有的请求数据都使用[Mock.js](https://github.com/nuysoft/Mock)模拟,提前了解和学习这些知识会对使用本项目有很大的帮助。 +你需要在本地安装 [node](http://nodejs.org/) 和 [git](https://git-scm.com/)。本项目技术栈基于 [ES2015+](http://es6.ruanyifeng.com/)、[vue](https://cn.vuejs.org/index.html)、[vuex](https://vuex.vuejs.org/zh-cn/)、[vue-router](https://router.vuejs.org/zh-cn/) 、[axios](https://github.com/axios/axios) 和 [element-ui](https://github.com/ElemeFE/element),所有的请求数据都使用[Mock.js](https://github.com/nuysoft/Mock)模拟,提前了解和学习这些知识会对使用本项目有很大的帮助。 同时配套一个系列的教程文章,如何从零构建后一个完整的后台项目,建议大家先看完这些文章再来实践本项目 - [手摸手,带你用 vue 撸后台 系列一(基础篇)](https://juejin.im/post/59097cd7a22b9d0065fb61d2) @@ -52,7 +54,6 @@ - [手摸手,带你封装一个 vue component](https://segmentfault.com/a/1190000009090836) - [手摸手,带你优雅的使用 icon](https://juejin.im/post/59bb864b5188257e7a427c09) - 响应需求,开了一个qq群 `591724180` 方便大家交流 或者加入该群主 **[圈子](https://jianshiapp.com/circles/1209)** 楼主会经常分享一些技术相关的东西 @@ -60,6 +61,8 @@ **本项目并不是一个脚手架,更倾向于是一个集成解决方案** + **注意:该项目使用 element-ui@2.3.0+ 版本,所以最低兼容 vue@2.5.0+** + **该项目不支持低版本浏览器(如ie),有需求请自行添加polyfill [详情](https://github.com/PanJiaChen/vue-element-admin/wiki#babel-polyfill)**

@@ -68,39 +71,65 @@ ## 功能 ``` -- 登录/注销 +- 登录 / 注销 + - 权限验证 + - 页面权限 + - 指令权限 + - 二步登录 + - 多环境发布 -- 动态侧边栏(支持多级路由) -- 动态面包屑 -- 国际化多语言 -- 多种动态换肤 -- 快捷导航(标签页) -- 富文本编辑器 -- Markdown编辑器 -- JSON编辑器 -- Screenfull全屏 -- 列表拖拽 -- Svg Sprite 图标 + - dev sit stage prod + +- 全局功能 + - 国际化多语言 + - 多种动态换肤 + - 动态侧边栏(支持多级路由嵌套) + - 动态面包屑 + - 快捷导航(标签页) + - Svg Sprite 图标 + - 本地mock数据 + - Screenfull全屏 + - 自适应收缩侧边栏 + +- 编辑器 + - 富文本 + - Markdown + - JSON 等多格式 + +- Excel + - 导出excel + - 导出zip + - 导入excel + - 前端可视化excel + +- 表格 + - 动态表格 + - 拖拽表格 + - 树形表格 + - 内联编辑 + +- 错误页面 + - 401 + - 404 + +- 組件 + - 头像上传 + - 返回顶部 + - 拖拽Dialog + - 拖拽看板 + - 列表拖拽 + - SplitPane + - Dropzone + - Sticky + - CountTo + +- 综合实例 +- 错误日志 - Dashboard -- 本地mock数据 +- 引导页 - Echarts 图表 - Clipboard(剪贴复制) -- 401/404错误页面 -- 错误日志 -- 导出excel -- 导出zip -- 前端可视化excel -- Table example -- 动态table example -- 拖拽table example -- 内联编辑table example -- Form example -- 二步登录 -- SplitPane -- Dropzone -- Sticky -- CountTo - Markdown2html ``` @@ -125,7 +154,7 @@ npm run dev # 构建测试环境 npm run build:sit -# 构建生成环境 +# 构建生产环境 npm run build:prod ``` @@ -144,7 +173,7 @@ npm run lint npm run lint -- --fix ``` -更多信息请参考 [使用文档](https://panjiachen.github.io/vue-element-admin-site/#/deploy) +更多信息请参考 [使用文档](https://panjiachen.github.io/vue-element-admin-site/zh/) ## Changelog Detailed changes for each release are documented in the [release notes](https://github.com/PanJiaChen/vue-element-admin/releases). diff --git a/build/build.js b/build/build.js index fc793972..fe24ac8f 100644 --- a/build/build.js +++ b/build/build.js @@ -8,9 +8,10 @@ const chalk = require('chalk') const webpack = require('webpack') const config = require('../config') const webpackConfig = require('./webpack.prod.conf') -const server = require('pushstate-server') +var connect = require('connect'); +var serveStatic = require('serve-static') -var spinner = ora('building for '+ process.env.env_config+ ' environment...' ) +const spinner = ora('building for ' + process.env.env_config + ' environment...') spinner.start() rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { @@ -27,22 +28,29 @@ rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { }) + '\n\n') if (stats.hasErrors()) { - console.log(chalk.red(' Build failed with errors.\n')) + console.log(chalk.red(' Build failed with errors.\n')) process.exit(1) } - console.log(chalk.cyan(' Build complete.\n')) + console.log(chalk.cyan(' Build complete.\n')) console.log(chalk.yellow( - ' Tip: built files are meant to be served over an HTTP server.\n' + - ' Opening index.html over file:// won\'t work.\n' + ' Tip: built files are meant to be served over an HTTP server.\n' + + ' Opening index.html over file:// won\'t work.\n' )) - if(process.env.npm_config_preview){ - server.start({ - port: 9526, - directory: './dist', - file: '/index.html' + + if (process.env.npm_config_preview) { + const port = 9526 + const host = "http://localhost:" + port + const basePath = config.build.assetsPublicPath + const app = connect() + + app.use(basePath, serveStatic('./dist', { + 'index': ['index.html', '/'] + })) + + app.listen(port, function () { + console.log(chalk.green(`> Listening at http://localhost:${port}${basePath}`)) }); - console.log('> Listening at ' + 'http://localhost:9526' + '\n') } }) }) diff --git a/build/webpack.base.conf.js b/build/webpack.base.conf.js index 97bc6e2b..9936a877 100644 --- a/build/webpack.base.conf.js +++ b/build/webpack.base.conf.js @@ -34,7 +34,6 @@ module.exports = { resolve: { extensions: ['.js', '.vue', '.json'], alias: { - 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src'), } }, diff --git a/config/dev.env.js b/config/dev.env.js index d1e29d4e..68ddea56 100644 --- a/config/dev.env.js +++ b/config/dev.env.js @@ -1,5 +1,5 @@ module.exports = { - NODE_ENV: '"development"', - ENV_CONFIG: '"dev"', - BASE_API: '"https://api-dev"' + NODE_ENV: '"development"', + ENV_CONFIG: '"dev"', + BASE_API: '"https://api-dev"' } diff --git a/config/index.js b/config/index.js index 7ec80132..92c4a172 100644 --- a/config/index.js +++ b/config/index.js @@ -13,7 +13,10 @@ module.exports = { proxyTable: {}, // Various Dev Server settings - host: 'localhost', // can be overwritten by process.env.HOST + + // can be overwritten by process.env.HOST + // if you want dev by ip, please set host: '0.0.0.0' + host: 'localhost', port: 9527, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined autoOpenBrowser: true, errorOverlay: true, @@ -33,7 +36,7 @@ module.exports = { */ // https://webpack.js.org/configuration/devtool/#development - devtool: 'eval-source-map', + devtool: '#cheap-source-map', // If you have problems debugging vue-files in devtools, // set this to false - it *may* help @@ -56,13 +59,18 @@ module.exports = { assetsRoot: path.resolve(__dirname, '../dist'), assetsSubDirectory: 'static', - // you can set by youself according to actual condition - assetsPublicPath: './', + /** + * You can set by youself according to actual condition + * You will need to set this if you plan to deploy your site under a sub path, + * for example GitHub pages. If you plan to deploy your site to https://foo.github.io/bar/, + * then assetsPublicPath should be set to "/bar/". + * In most cases please use '/' !!! + */ + assetsPublicPath: '/vue-element-admin/', // If you are deployed on the root path, please use '/' /** * Source Maps */ - productionSourceMap: false, // https://webpack.js.org/configuration/devtool/#production devtool: '#source-map', diff --git a/config/prod.env.js b/config/prod.env.js index 0c43ea73..bfcd6d27 100644 --- a/config/prod.env.js +++ b/config/prod.env.js @@ -1,5 +1,5 @@ module.exports = { - NODE_ENV: '"production"', - ENV_CONFIG: '"prod"', - BASE_API: '"https://api-prod"' + NODE_ENV: '"production"', + ENV_CONFIG: '"prod"', + BASE_API: '"https://api-prod"' } diff --git a/config/sit.env.js b/config/sit.env.js index 296a3de6..93178e80 100644 --- a/config/sit.env.js +++ b/config/sit.env.js @@ -1,5 +1,5 @@ module.exports = { - NODE_ENV: '"production"', - ENV_CONFIG: '"sit"', - BASE_API: '"https://api-sit"' + NODE_ENV: '"production"', + ENV_CONFIG: '"sit"', + BASE_API: '"https://api-sit"' } diff --git a/gifs/2login.gif b/gifs/2login.gif deleted file mode 100644 index 4b2b64da..00000000 Binary files a/gifs/2login.gif and /dev/null differ diff --git a/gifs/dynamictable.gif b/gifs/dynamictable.gif deleted file mode 100644 index ca666e53..00000000 Binary files a/gifs/dynamictable.gif and /dev/null differ diff --git a/gifs/echarts.gif b/gifs/echarts.gif deleted file mode 100644 index 11ad2a56..00000000 Binary files a/gifs/echarts.gif and /dev/null differ diff --git a/gifs/editor.gif b/gifs/editor.gif deleted file mode 100644 index 1ebb9c6c..00000000 Binary files a/gifs/editor.gif and /dev/null differ diff --git a/gifs/errorlog.gif b/gifs/errorlog.gif deleted file mode 100644 index d37c7085..00000000 Binary files a/gifs/errorlog.gif and /dev/null differ diff --git a/gifs/excel.png b/gifs/excel.png deleted file mode 100644 index e536774c..00000000 Binary files a/gifs/excel.png and /dev/null differ diff --git a/gifs/leftmenu.gif b/gifs/leftmenu.gif deleted file mode 100644 index f3ca2bd9..00000000 Binary files a/gifs/leftmenu.gif and /dev/null differ diff --git a/gifs/login.png b/gifs/login.png deleted file mode 100644 index a923b271..00000000 Binary files a/gifs/login.png and /dev/null differ diff --git a/gifs/order.gif b/gifs/order.gif deleted file mode 100644 index d038b06d..00000000 Binary files a/gifs/order.gif and /dev/null differ diff --git a/gifs/table.gif b/gifs/table.gif deleted file mode 100644 index 31dcd144..00000000 Binary files a/gifs/table.gif and /dev/null differ diff --git a/gifs/tabs.gif b/gifs/tabs.gif deleted file mode 100644 index 331d192f..00000000 Binary files a/gifs/tabs.gif and /dev/null differ diff --git a/gifs/theme.gif b/gifs/theme.gif deleted file mode 100644 index 47f48d54..00000000 Binary files a/gifs/theme.gif and /dev/null differ diff --git a/gifs/upload1.gif b/gifs/upload1.gif deleted file mode 100644 index 37a5db22..00000000 Binary files a/gifs/upload1.gif and /dev/null differ diff --git a/gifs/uploadAvatar.gif b/gifs/uploadAvatar.gif deleted file mode 100644 index c689b9a2..00000000 Binary files a/gifs/uploadAvatar.gif and /dev/null differ diff --git a/index.html b/index.html index a485ce88..489d1a53 100644 --- a/index.html +++ b/index.html @@ -1,15 +1,15 @@ - - - - - - vue-element-admin - - - -

- - + + + + + + vue-element-admin + + + +
+ + diff --git a/package.json b/package.json index 8a5fdac0..e8ee8955 100644 --- a/package.json +++ b/package.json @@ -1,33 +1,56 @@ { "name": "vue-element-admin", - "version": "3.5.1", + "version": "3.7.3", "description": "A magical vue admin. Typical templates for enterprise applications. Newest development stack of vue. Lots of awesome features", "author": "Pan ", "license": "MIT", - "private": true, "scripts": { - "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", + "dev": "cross-env BABEL_ENV=development webpack-dev-server --inline --progress --config build/webpack.dev.conf.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", "lint": "eslint --ext .js,.vue src", - "test": "npm run lint" + "test": "npm run lint", + "precommit": "lint-staged" + }, + "lint-staged": { + "src/**/*.{js,vue}": [ + "eslint --fix", + "git add" + ] + }, + "keywords": [ + "vue", + "element-ui", + "admin", + "management-system", + "admin-template" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/PanJiaChen/vue-element-admin.git" + }, + "bugs": { + "url": "https://github.com/PanJiaChen/vue-element-admin/issues" }, "dependencies": { "axios": "0.17.1", "clipboard": "1.7.1", "codemirror": "5.32.0", + "connect": "3.6.6", + "driver.js": "0.5.2", "dropzone": "5.2.0", "echarts": "3.8.5", - "element-ui": "2.0.8", + "element-ui": "2.3.2", "file-saver": "1.3.3", "font-awesome": "4.7.0", "js-cookie": "2.2.0", - "jsonlint": "1.6.2", + "jsonlint": "1.6.3", "jszip": "3.1.5", "mockjs": "1.0.1-beta3", "normalize.css": "7.0.0", "nprogress": "0.2.0", "screenfull": "3.3.2", + "serve-static": "1.13.2", "showdown": "1.8.5", "simplemde": "1.11.2", "sortablejs": "1.7.0", @@ -37,7 +60,7 @@ "vue-multiselect": "2.0.8", "vue-router": "3.0.1", "vue-splitpane": "1.0.2", - "vuedraggable": "2.15.0", + "vuedraggable": "^2.16.0", "vuex": "3.0.1", "xlsx": "^0.11.16" }, @@ -47,6 +70,7 @@ "babel-eslint": "8.0.3", "babel-helper-vue-jsx-merge-props": "2.0.3", "babel-loader": "7.1.2", + "babel-plugin-dynamic-import-node": "^1.2.0", "babel-plugin-syntax-jsx": "6.18.0", "babel-plugin-transform-runtime": "6.23.0", "babel-plugin-transform-vue-jsx": "3.5.0", @@ -64,6 +88,8 @@ "file-loader": "1.1.5", "friendly-errors-webpack-plugin": "1.6.1", "html-webpack-plugin": "2.30.1", + "husky": "0.14.3", + "lint-staged": "7.2.0", "node-notifier": "5.1.2", "node-sass": "^4.7.2", "optimize-css-assets-webpack-plugin": "3.2.0", @@ -72,7 +98,6 @@ "postcss-import": "11.0.0", "postcss-loader": "2.0.9", "postcss-url": "7.3.0", - "pushstate-server": "3.0.1", "rimraf": "2.6.2", "sass-loader": "6.0.6", "script-loader": "0.7.2", @@ -81,7 +106,7 @@ "svg-sprite-loader": "3.5.2", "uglifyjs-webpack-plugin": "1.1.3", "url-loader": "0.6.2", - "vue-loader": "13.5.0", + "vue-loader": "13.7.2", "vue-style-loader": "3.0.3", "vue-template-compiler": "2.5.10", "webpack": "3.10.0", diff --git a/src/App.vue b/src/App.vue index b39696e2..690cfc98 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,11 +1,11 @@ diff --git a/src/api/article.js b/src/api/article.js index 9eacd90d..f54b8af6 100644 --- a/src/api/article.js +++ b/src/api/article.js @@ -8,10 +8,11 @@ export function fetchList(query) { }) } -export function fetchArticle() { +export function fetchArticle(id) { return request({ url: '/article/detail', - method: 'get' + method: 'get', + params: { id } }) } diff --git a/src/components/BackToTop/index.vue b/src/components/BackToTop/index.vue index cbb1f21d..de953821 100644 --- a/src/components/BackToTop/index.vue +++ b/src/components/BackToTop/index.vue @@ -25,14 +25,16 @@ export default { }, customStyle: { type: Object, - default: { - right: '50px', - bottom: '50px', - width: '40px', - height: '40px', - 'border-radius': '4px', - 'line-height': '45px', - background: '#e7eaf1' + default: function() { + return { + right: '50px', + bottom: '50px', + width: '40px', + height: '40px', + 'border-radius': '4px', + 'line-height': '45px', + background: '#e7eaf1' + } } }, transitionName: { diff --git a/src/components/Charts/keyboard.vue b/src/components/Charts/keyboard.vue index 4c2a0bbd..4b1bd499 100644 --- a/src/components/Charts/keyboard.vue +++ b/src/components/Charts/keyboard.vue @@ -4,8 +4,10 @@ - --> + + diff --git a/src/components/ImageCropper/lang.js b/src/components/ImageCropper/lang.js deleted file mode 100644 index 264f914c..00000000 --- a/src/components/ImageCropper/lang.js +++ /dev/null @@ -1,41 +0,0 @@ -const langBag = { - zh: { - hint: '点击,或拖动图片至此处', - loading: '正在上传……', - noSupported: '浏览器不支持该功能,请使用IE10以上或其他现在浏览器!', - success: '上传成功', - fail: '图片上传失败', - preview: '头像预览', - btn: { - off: '取消', - close: '关闭', - back: '上一步', - save: '保存' - }, - error: { - onlyImg: '仅限图片格式', - outOfSize: '单文件大小不能超过 ', - lowestPx: '图片最低像素为(宽*高):' - } - }, - en: { - hint: 'Click, or drag the file here', - loading: 'Uploading……', - noSupported: 'Browser does not support, please use IE10+ or other browsers', - success: 'Upload success', - fail: 'Upload failed', - preview: 'Preview', - btn: { - off: 'Cancel', - close: 'Close', - back: 'Back', - save: 'Save' - }, - error: { - onlyImg: 'Image only', - outOfSize: 'Image exceeds size limit: ', - lowestPx: 'The lowest pixel in the image: ' - } - } -} -export default langBag diff --git a/src/components/ImageCropper/upload.css b/src/components/ImageCropper/upload.css deleted file mode 100644 index d01dc40c..00000000 --- a/src/components/ImageCropper/upload.css +++ /dev/null @@ -1,691 +0,0 @@ -@charset "UTF-8"; -@-webkit-keyframes vicp_progress { - 0% { - background-position-y: 0; - } - 100% { - background-position-y: 40px; - } -} - -@keyframes vicp_progress { - 0% { - background-position-y: 0; - } - 100% { - background-position-y: 40px; - } -} - -@-webkit-keyframes vicp { - 0% { - opacity: 0; - -webkit-transform: scale(0) translatey(-60px); - transform: scale(0) translatey(-60px); - } - 100% { - opacity: 1; - -webkit-transform: scale(1) translatey(0); - transform: scale(1) translatey(0); - } -} - -@keyframes vicp { - 0% { - opacity: 0; - -webkit-transform: scale(0) translatey(-60px); - transform: scale(0) translatey(-60px); - } - 100% { - opacity: 1; - -webkit-transform: scale(1) translatey(0); - transform: scale(1) translatey(0); - } -} - -.vue-image-crop-upload { - position: fixed; - display: block; - -webkit-box-sizing: border-box; - box-sizing: border-box; - z-index: 10000; - top: 0; - bottom: 0; - left: 0; - right: 0; - width: 100%; - height: 100%; - background-color: rgba(0, 0, 0, 0.65); - -webkit-tap-highlight-color: transparent; - -moz-tap-highlight-color: transparent; -} - -.vue-image-crop-upload .vicp-wrap { - -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23); - box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23); - position: fixed; - display: block; - -webkit-box-sizing: border-box; - box-sizing: border-box; - z-index: 10000; - top: 0; - bottom: 0; - left: 0; - right: 0; - margin: auto; - width: 600px; - height: 330px; - padding: 25px; - background-color: #fff; - border-radius: 2px; - -webkit-animation: vicp 0.12s ease-in; - animation: vicp 0.12s ease-in; -} - -.vue-image-crop-upload .vicp-wrap .vicp-close { - position: absolute; - right: -30px; - top: -30px; -} - -.vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4 { - position: relative; - display: block; - width: 30px; - height: 30px; - cursor: pointer; - -webkit-transition: -webkit-transform 0.18s; - transition: -webkit-transform 0.18s; - transition: transform 0.18s; - transition: transform 0.18s, -webkit-transform 0.18s; - -webkit-transform: rotate(0); - -ms-transform: rotate(0); - transform: rotate(0); -} - -.vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4::after, .vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4::before { - -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23); - box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23); - content: ''; - position: absolute; - top: 12px; - left: 4px; - width: 20px; - height: 3px; - -webkit-transform: rotate(45deg); - -ms-transform: rotate(45deg); - transform: rotate(45deg); - background-color: #fff; -} - -.vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4::after { - -webkit-transform: rotate(-45deg); - -ms-transform: rotate(-45deg); - transform: rotate(-45deg); -} - -.vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4:hover { - -webkit-transform: rotate(90deg); - -ms-transform: rotate(90deg); - transform: rotate(90deg); -} - -.vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area { - position: relative; - padding: 35px; - height: 200px; - background-color: rgba(0, 0, 0, 0.03); - text-align: center; - border: 1px dashed rgba(0, 0, 0, 0.08); - overflow: hidden; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-icon1 { - display: block; - margin: 0 auto 6px; - width: 42px; - height: 42px; - overflow: hidden; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-icon1 .vicp-icon1-arrow { - display: block; - margin: 0 auto; - width: 0; - height: 0; - border-bottom: 14.7px solid rgba(0, 0, 0, 0.3); - border-left: 14.7px solid transparent; - border-right: 14.7px solid transparent; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-icon1 .vicp-icon1-body { - display: block; - width: 12.6px; - height: 14.7px; - margin: 0 auto; - background-color: rgba(0, 0, 0, 0.3); -} - -.vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-icon1 .vicp-icon1-bottom { - -webkit-box-sizing: border-box; - box-sizing: border-box; - display: block; - height: 12.6px; - border: 6px solid rgba(0, 0, 0, 0.3); - border-top: none; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-hint { - display: block; - padding: 15px; - font-size: 14px; - color: #666; - line-height: 30px; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-no-supported-hint { - display: block; - position: absolute; - top: 0; - left: 0; - padding: 30px; - width: 100%; - height: 60px; - line-height: 30px; - background-color: #eee; - text-align: center; - color: #666; - font-size: 14px; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area:hover { - cursor: pointer; - border-color: rgba(0, 0, 0, 0.1); - background-color: rgba(0, 0, 0, 0.05); -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop { - overflow: hidden; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left { - float: left; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-img-container { - position: relative; - display: block; - width: 240px; - height: 180px; - background-color: #e5e5e0; - overflow: hidden; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-img-container .vicp-img { - position: absolute; - display: block; - cursor: move; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-img-container .vicp-img-shade { - -webkit-box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18); - box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18); - position: absolute; - background-color: rgba(241, 242, 243, 0.8); -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-img-container .vicp-img-shade.vicp-img-shade-1 { - top: 0; - left: 0; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-img-container .vicp-img-shade.vicp-img-shade-2 { - bottom: 0; - right: 0; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range { - position: relative; - margin: 30px 0; - width: 240px; - height: 18px; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon5, -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon6 { - position: absolute; - top: 0; - width: 18px; - height: 18px; - border-radius: 100%; - background-color: rgba(0, 0, 0, 0.08); -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon5:hover, -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon6:hover { - -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12); - box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12); - cursor: pointer; - background-color: rgba(0, 0, 0, 0.14); -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon5 { - left: 0; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon5::before { - position: absolute; - content: ''; - display: block; - left: 3px; - top: 8px; - width: 12px; - height: 2px; - background-color: #fff; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon6 { - right: 0; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon6::before { - position: absolute; - content: ''; - display: block; - left: 3px; - top: 8px; - width: 12px; - height: 2px; - background-color: #fff; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon6::after { - position: absolute; - content: ''; - display: block; - top: 3px; - left: 8px; - width: 2px; - height: 12px; - background-color: #fff; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range] { - display: block; - padding-top: 5px; - margin: 0 auto; - width: 180px; - height: 8px; - vertical-align: top; - background: transparent; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - cursor: pointer; - /* 滑块 - ---------------------------------------------------------------*/ - /* 轨道 - ---------------------------------------------------------------*/ -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:focus { - outline: none; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-webkit-slider-thumb { - -webkit-box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18); - box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18); - -webkit-appearance: none; - appearance: none; - margin-top: -3px; - width: 12px; - height: 12px; - background-color: #61c091; - border-radius: 100%; - border: none; - -webkit-transition: 0.2s; - transition: 0.2s; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-moz-range-thumb { - box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18); - -moz-appearance: none; - appearance: none; - width: 12px; - height: 12px; - background-color: #61c091; - border-radius: 100%; - border: none; - -webkit-transition: 0.2s; - transition: 0.2s; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-ms-thumb { - box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18); - appearance: none; - width: 12px; - height: 12px; - background-color: #61c091; - border: none; - border-radius: 100%; - -webkit-transition: 0.2s; - transition: 0.2s; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:active::-moz-range-thumb { - box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23); - width: 14px; - height: 14px; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:active::-ms-thumb { - box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23); - width: 14px; - height: 14px; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:active::-webkit-slider-thumb { - -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23); - box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23); - margin-top: -4px; - width: 14px; - height: 14px; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-webkit-slider-runnable-track { - -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12); - box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12); - width: 100%; - height: 6px; - cursor: pointer; - border-radius: 2px; - border: none; - background-color: rgba(68, 170, 119, 0.3); -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-moz-range-track { - box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12); - width: 100%; - height: 6px; - cursor: pointer; - border-radius: 2px; - border: none; - background-color: rgba(68, 170, 119, 0.3); -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-ms-track { - box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12); - width: 100%; - cursor: pointer; - background: transparent; - border-color: transparent; - color: transparent; - height: 6px; - border-radius: 2px; - border: none; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-ms-fill-lower { - background-color: rgba(68, 170, 119, 0.3); -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-ms-fill-upper { - background-color: rgba(68, 170, 119, 0.15); -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:focus::-webkit-slider-runnable-track { - background-color: rgba(68, 170, 119, 0.5); -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:focus::-moz-range-track { - background-color: rgba(68, 170, 119, 0.5); -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:focus::-ms-fill-lower { - background-color: rgba(68, 170, 119, 0.45); -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:focus::-ms-fill-upper { - background-color: rgba(68, 170, 119, 0.25); -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right { - float: right; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview { - height: 150px; - overflow: hidden; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview .vicp-preview-item { - position: relative; - padding: 5px; - width: 100px; - height: 100px; - float: left; - margin-right: 16px; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview .vicp-preview-item span { - position: absolute; - bottom: -30px; - width: 100%; - font-size: 14px; - color: #bbb; - display: block; - text-align: center; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview .vicp-preview-item img { - position: absolute; - display: block; - top: 0; - bottom: 0; - left: 0; - right: 0; - margin: auto; - padding: 3px; - background-color: #fff; - border: 1px solid rgba(0, 0, 0, 0.15); - overflow: hidden; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview .vicp-preview-item:last-child { - margin-right: 0; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview .vicp-preview-item:last-child img { - border-radius: 100%; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload { - position: relative; - padding: 35px; - height: 200px; - background-color: rgba(0, 0, 0, 0.03); - text-align: center; - border: 1px dashed #ddd; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-loading { - display: block; - padding: 15px; - font-size: 16px; - color: #999; - line-height: 30px; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-progress-wrap { - margin-top: 12px; - background-color: rgba(0, 0, 0, 0.08); - border-radius: 3px; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-progress-wrap .vicp-progress { - position: relative; - display: block; - height: 5px; - border-radius: 3px; - background-color: #4a7; - -webkit-box-shadow: 0 2px 6px 0 rgba(68, 170, 119, 0.3); - box-shadow: 0 2px 6px 0 rgba(68, 170, 119, 0.3); - -webkit-transition: width 0.15s linear; - transition: width 0.15s linear; - background-image: -webkit-linear-gradient(135deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); - background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); - background-size: 40px 40px; - -webkit-animation: vicp_progress 0.5s linear infinite; - animation: vicp_progress 0.5s linear infinite; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-progress-wrap .vicp-progress::after { - content: ''; - position: absolute; - display: block; - top: -3px; - right: -3px; - width: 9px; - height: 9px; - border: 1px solid rgba(245, 246, 247, 0.7); - -webkit-box-shadow: 0 1px 4px 0 rgba(68, 170, 119, 0.7); - box-shadow: 0 1px 4px 0 rgba(68, 170, 119, 0.7); - border-radius: 100%; - background-color: #4a7; -} - -.vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-error, -.vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-success { - height: 100px; - line-height: 100px; -} - -.vue-image-crop-upload .vicp-wrap .vicp-operate { - position: absolute; - right: 20px; - bottom: 20px; -} - -.vue-image-crop-upload .vicp-wrap .vicp-operate a { - position: relative; - float: left; - display: block; - margin-left: 10px; - width: 100px; - height: 36px; - line-height: 36px; - text-align: center; - cursor: pointer; - font-size: 14px; - color: #4a7; - border-radius: 2px; - overflow: hidden; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.vue-image-crop-upload .vicp-wrap .vicp-operate a:hover { - background-color: rgba(0, 0, 0, 0.03); -} - -.vue-image-crop-upload .vicp-wrap .vicp-error, -.vue-image-crop-upload .vicp-wrap .vicp-success { - display: block; - font-size: 14px; - line-height: 24px; - height: 24px; - color: #d10; - text-align: center; - vertical-align: top; -} - -.vue-image-crop-upload .vicp-wrap .vicp-success { - color: #4a7; -} - -.vue-image-crop-upload .vicp-wrap .vicp-icon3 { - position: relative; - display: inline-block; - width: 20px; - height: 20px; - top: 4px; -} - -.vue-image-crop-upload .vicp-wrap .vicp-icon3::after { - position: absolute; - top: 3px; - left: 6px; - width: 6px; - height: 10px; - border-width: 0 2px 2px 0; - border-color: #4a7; - border-style: solid; - -webkit-transform: rotate(45deg); - -ms-transform: rotate(45deg); - transform: rotate(45deg); - content: ''; -} - -.vue-image-crop-upload .vicp-wrap .vicp-icon2 { - position: relative; - display: inline-block; - width: 20px; - height: 20px; - top: 4px; -} - -.vue-image-crop-upload .vicp-wrap .vicp-icon2::after, .vue-image-crop-upload .vicp-wrap .vicp-icon2::before { - content: ''; - position: absolute; - top: 9px; - left: 4px; - width: 13px; - height: 2px; - background-color: #d10; - -webkit-transform: rotate(45deg); - -ms-transform: rotate(45deg); - transform: rotate(45deg); -} - -.vue-image-crop-upload .vicp-wrap .vicp-icon2::after { - -webkit-transform: rotate(-45deg); - -ms-transform: rotate(-45deg); - transform: rotate(-45deg); -} - -.e-ripple { - position: absolute; - border-radius: 100%; - background-color: rgba(0, 0, 0, 0.15); - background-clip: padding-box; - pointer-events: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - -webkit-transform: scale(0); - -ms-transform: scale(0); - transform: scale(0); - opacity: 1; -} - -.e-ripple.z-active { - opacity: 0; - -webkit-transform: scale(2); - -ms-transform: scale(2); - transform: scale(2); - -webkit-transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out; - transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out; - transition: opacity 1.2s ease-out, transform 0.6s ease-out; - transition: opacity 1.2s ease-out, transform 0.6s ease-out, -webkit-transform 0.6s ease-out; -} \ No newline at end of file diff --git a/src/components/ImageCropper/utils.js b/src/components/ImageCropper/utils.js deleted file mode 100644 index 0ccd3af0..00000000 --- a/src/components/ImageCropper/utils.js +++ /dev/null @@ -1,58 +0,0 @@ -/* eslint-disable */ - -/** - * - * @param e - * @param arg_opts - * @returns {boolean} - */ -export function effectRipple(e, arg_opts) { - let opts = Object.assign({ - ele: e.target, // 波纹作用元素 - type: 'hit', // hit点击位置扩散 center中心点扩展 - bgc: 'rgba(0, 0, 0, 0.15)' // 波纹颜色 - }, arg_opts), - target = opts.ele; - if (target) { - let rect = target.getBoundingClientRect(), - ripple = target.querySelector('.e-ripple'); - if (!ripple) { - ripple = document.createElement('span'); - ripple.className = 'e-ripple'; - ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px'; - target.appendChild(ripple); - } else { - ripple.className = 'e-ripple'; - } - switch (opts.type) { - case 'center': - ripple.style.top = (rect.height / 2 - ripple.offsetHeight / 2) + 'px'; - ripple.style.left = (rect.width / 2 - ripple.offsetWidth / 2) + 'px'; - break; - default: - ripple.style.top = (e.pageY - rect.top - ripple.offsetHeight / 2 - document.body.scrollTop) + 'px'; - ripple.style.left = (e.pageX - rect.left - ripple.offsetWidth / 2 - document.body.scrollLeft) + 'px'; - } - ripple.style.backgroundColor = opts.bgc; - ripple.className = 'e-ripple z-active'; - return false; - } -} -// database64文件格式转换为2进制 -/** - * - * @param data - * @param mime - * @returns {*} - */ -export function data2blob(data, mime) { - // dataURL 的格式为 “data:image/png;base64,****”,逗号之前都是一些说明性的文字,我们只需要逗号之后的就行了 - data = data.split(',')[1]; - data = window.atob(data); - var ia = new Uint8Array(data.length); - for (var i = 0; i < data.length; i++) { - ia[i] = data.charCodeAt(i); - } - // canvas.toDataURL 返回的默认格式就是 image/png - return new Blob([ia], {type: mime}); -}; diff --git a/src/components/ImageCropper/utils/data2blob.js b/src/components/ImageCropper/utils/data2blob.js new file mode 100755 index 00000000..9c47f8af --- /dev/null +++ b/src/components/ImageCropper/utils/data2blob.js @@ -0,0 +1,19 @@ +/** + * database64文件格式转换为2进制 + * + * @param {[String]} data dataURL 的格式为 “data:image/png;base64,****”,逗号之前都是一些说明性的文字,我们只需要逗号之后的就行了 + * @param {[String]} mime [description] + * @return {[blob]} [description] + */ +export default function(data, mime) { + data = data.split(',')[1] + data = window.atob(data) + var ia = new Uint8Array(data.length) + for (var i = 0; i < data.length; i++) { + ia[i] = data.charCodeAt(i) + } + // canvas.toDataURL 返回的默认格式就是 image/png + return new Blob([ia], { + type: mime + }) +} diff --git a/src/components/ImageCropper/utils/effectRipple.js b/src/components/ImageCropper/utils/effectRipple.js new file mode 100755 index 00000000..46a01640 --- /dev/null +++ b/src/components/ImageCropper/utils/effectRipple.js @@ -0,0 +1,39 @@ +/** + * 点击波纹效果 + * + * @param {[event]} e [description] + * @param {[Object]} arg_opts [description] + * @return {[bollean]} [description] + */ +export default function(e, arg_opts) { + var opts = Object.assign({ + ele: e.target, // 波纹作用元素 + type: 'hit', // hit点击位置扩散center中心点扩展 + bgc: 'rgba(0, 0, 0, 0.15)' // 波纹颜色 + }, arg_opts) + var target = opts.ele + if (target) { + var rect = target.getBoundingClientRect() + var ripple = target.querySelector('.e-ripple') + if (!ripple) { + ripple = document.createElement('span') + ripple.className = 'e-ripple' + ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px' + target.appendChild(ripple) + } else { + ripple.className = 'e-ripple' + } + switch (opts.type) { + case 'center': + ripple.style.top = (rect.height / 2 - ripple.offsetHeight / 2) + 'px' + ripple.style.left = (rect.width / 2 - ripple.offsetWidth / 2) + 'px' + break + default: + ripple.style.top = (e.pageY - rect.top - ripple.offsetHeight / 2 - document.body.scrollTop) + 'px' + ripple.style.left = (e.pageX - rect.left - ripple.offsetWidth / 2 - document.body.scrollLeft) + 'px' + } + ripple.style.backgroundColor = opts.bgc + ripple.className = 'e-ripple z-active' + return false + } +} diff --git a/src/components/ImageCropper/utils/language.js b/src/components/ImageCropper/utils/language.js new file mode 100755 index 00000000..727872d9 --- /dev/null +++ b/src/components/ImageCropper/utils/language.js @@ -0,0 +1,232 @@ +export default { + zh: { + hint: '点击,或拖动图片至此处', + loading: '正在上传……', + noSupported: '浏览器不支持该功能,请使用IE10以上或其他现在浏览器!', + success: '上传成功', + fail: '图片上传失败', + preview: '头像预览', + btn: { + off: '取消', + close: '关闭', + back: '上一步', + save: '保存' + }, + error: { + onlyImg: '仅限图片格式', + outOfSize: '单文件大小不能超过 ', + lowestPx: '图片最低像素为(宽*高):' + } + }, + 'zh-tw': { + hint: '點擊,或拖動圖片至此處', + loading: '正在上傳……', + noSupported: '瀏覽器不支持該功能,請使用IE10以上或其他現代瀏覽器!', + success: '上傳成功', + fail: '圖片上傳失敗', + preview: '頭像預覽', + btn: { + off: '取消', + close: '關閉', + back: '上一步', + save: '保存' + }, + error: { + onlyImg: '僅限圖片格式', + outOfSize: '單文件大小不能超過 ', + lowestPx: '圖片最低像素為(寬*高):' + } + }, + en: { + hint: 'Click or drag the file here to upload', + loading: 'Uploading…', + noSupported: 'Browser is not supported, please use IE10+ or other browsers', + success: 'Upload success', + fail: 'Upload failed', + preview: 'Preview', + btn: { + off: 'Cancel', + close: 'Close', + back: 'Back', + save: 'Save' + }, + error: { + onlyImg: 'Image only', + outOfSize: 'Image exceeds size limit: ', + lowestPx: 'Image\'s size is too low. Expected at least: ' + } + }, + ro: { + hint: 'Atinge sau trage fișierul aici', + loading: 'Se încarcă', + noSupported: 'Browser-ul tău nu suportă acest feature. Te rugăm încearcă cu alt browser.', + success: 'S-a încărcat cu succes', + fail: 'A apărut o problemă la încărcare', + preview: 'Previzualizează', + + btn: { + off: 'Anulează', + close: 'Închide', + back: 'Înapoi', + save: 'Salvează' + }, + + error: { + onlyImg: 'Doar imagini', + outOfSize: 'Imaginea depășește limita de: ', + loewstPx: 'Imaginea este prea mică; Minim: ' + } + }, + ru: { + hint: 'Нажмите, или перетащите файл в это окно', + loading: 'Загружаю……', + noSupported: 'Ваш браузер не поддерживается, пожалуйста, используйте IE10 + или другие браузеры', + success: 'Загрузка выполнена успешно', + fail: 'Ошибка загрузки', + preview: 'Предпросмотр', + btn: { + off: 'Отменить', + close: 'Закрыть', + back: 'Назад', + save: 'Сохранить' + }, + error: { + onlyImg: 'Только изображения', + outOfSize: 'Изображение превышает предельный размер: ', + lowestPx: 'Минимальный размер изображения: ' + } + }, + 'pt-br': { + hint: 'Clique ou arraste o arquivo aqui para carregar', + loading: 'Carregando…', + noSupported: 'Browser não suportado, use o IE10+ ou outro browser', + success: 'Sucesso ao carregar imagem', + fail: 'Falha ao carregar imagem', + preview: 'Pré-visualizar', + btn: { + off: 'Cancelar', + close: 'Fechar', + back: 'Voltar', + save: 'Salvar' + }, + error: { + onlyImg: 'Apenas imagens', + outOfSize: 'A imagem excede o limite de tamanho: ', + lowestPx: 'O tamanho da imagem é muito pequeno. Tamanho mínimo: ' + } + }, + fr: { + hint: 'Cliquez ou glissez le fichier ici.', + loading: 'Téléchargement…', + noSupported: 'Votre navigateur n\'est pas supporté. Utilisez IE10 + ou un autre navigateur s\'il vous plaît.', + success: 'Téléchargement réussit', + fail: 'Téléchargement echoué', + preview: 'Aperçu', + btn: { + off: 'Annuler', + close: 'Fermer', + back: 'Retour', + save: 'Enregistrer' + }, + error: { + onlyImg: 'Image uniquement', + outOfSize: 'L\'image sélectionnée dépasse la taille maximum: ', + lowestPx: 'L\'image sélectionnée est trop petite. Dimensions attendues: ' + } + }, + nl: { + hint: 'Klik hier of sleep een afbeelding in dit vlak', + loading: 'Uploaden…', + noSupported: 'Je browser wordt helaas niet ondersteund. Gebruik IE10+ of een andere browser.', + success: 'Upload succesvol', + fail: 'Upload mislukt', + preview: 'Voorbeeld', + btn: { + off: 'Annuleren', + close: 'Sluiten', + back: 'Terug', + save: 'Opslaan' + }, + error: { + onlyImg: 'Alleen afbeeldingen', + outOfSize: 'De afbeelding is groter dan: ', + lowestPx: 'De afbeelding is te klein! Minimale afmetingen: ' + } + }, + tr: { + hint: 'Tıkla veya yüklemek istediğini buraya sürükle', + loading: 'Yükleniyor…', + noSupported: 'Tarayıcı desteklenmiyor, lütfen IE10+ veya farklı tarayıcı kullanın', + success: 'Yükleme başarılı', + fail: 'Yüklemede hata oluştu', + preview: 'Önizle', + btn: { + off: 'İptal', + close: 'Kapat', + back: 'Geri', + save: 'Kaydet' + }, + error: { + onlyImg: 'Sadece resim', + outOfSize: 'Resim yükleme limitini aşıyor: ', + lowestPx: 'Resmin boyutu çok küçük. En az olması gereken: ' + } + }, + 'es-MX': { + hint: 'Selecciona o arrastra una imagen', + loading: 'Subiendo...', + noSupported: 'Tu navegador no es soportado, porfavor usa IE10+ u otros navegadores mas recientes', + success: 'Subido exitosamente', + fail: 'Sucedió un error', + preview: 'Vista previa', + btn: { + off: 'Cancelar', + close: 'Cerrar', + back: 'Atras', + save: 'Guardar' + }, + error: { + onlyImg: 'Unicamente imagenes', + outOfSize: 'La imagen excede el tamaño maximo:', + lowestPx: 'La imagen es demasiado pequeño. Se espera por lo menos:' + } + }, + de: { + hint: 'Klick hier oder zieh eine Datei hier rein zum Hochladen', + loading: 'Hochladen…', + noSupported: 'Browser wird nicht unterstützt, bitte verwende IE10+ oder andere Browser', + success: 'Upload erfolgreich', + fail: 'Upload fehlgeschlagen', + preview: 'Vorschau', + btn: { + off: 'Abbrechen', + close: 'Schließen', + back: 'Zurück', + save: 'Speichern' + }, + error: { + onlyImg: 'Nur Bilder', + outOfSize: 'Das Bild ist zu groß: ', + lowestPx: 'Das Bild ist zu klein. Mindestens: ' + } + }, + ja: { + hint: 'クリック・ドラッグしてファイルをアップロード', + loading: 'アップロード中...', + noSupported: 'このブラウザは対応されていません。IE10+かその他の主要ブラウザをお使いください。', + success: 'アップロード成功', + fail: 'アップロード失敗', + preview: 'プレビュー', + btn: { + off: 'キャンセル', + close: '閉じる', + back: '戻る', + save: '保存' + }, + error: { + onlyImg: '画像のみ', + outOfSize: '画像サイズが上限を超えています。上限: ', + lowestPx: '画像が小さすぎます。最小サイズ: ' + } + } +} diff --git a/src/components/ImageCropper/utils/mimes.js b/src/components/ImageCropper/utils/mimes.js new file mode 100755 index 00000000..e20c085c --- /dev/null +++ b/src/components/ImageCropper/utils/mimes.js @@ -0,0 +1,7 @@ +export default { + 'jpg': 'image/jpeg', + 'png': 'image/png', + 'gif': 'image/gif', + 'svg': 'image/svg+xml', + 'psd': 'image/photoshop' +} diff --git a/src/components/JsonEditor/index.vue b/src/components/JsonEditor/index.vue index 1f2b769a..b63f4438 100644 --- a/src/components/JsonEditor/index.vue +++ b/src/components/JsonEditor/index.vue @@ -53,11 +53,19 @@ export default { } - diff --git a/src/components/Kanban/index.vue b/src/components/Kanban/index.vue new file mode 100644 index 00000000..c16894eb --- /dev/null +++ b/src/components/Kanban/index.vue @@ -0,0 +1,89 @@ + + + + diff --git a/src/components/MarkdownEditor/index.vue b/src/components/MarkdownEditor/index.vue index cbec69a0..6dea8382 100644 --- a/src/components/MarkdownEditor/index.vue +++ b/src/components/MarkdownEditor/index.vue @@ -73,47 +73,44 @@ export default { }) }, destroyed() { + this.simplemde.toTextArea() this.simplemde = null } } - - - diff --git a/src/components/PanThumb/index.vue b/src/components/PanThumb/index.vue index 7b507805..f3478d6c 100644 --- a/src/components/PanThumb/index.vue +++ b/src/components/PanThumb/index.vue @@ -1,12 +1,12 @@ - - diff --git a/src/components/Sticky/index.vue b/src/components/Sticky/index.vue index 2c9657be..d3a698e8 100644 --- a/src/components/Sticky/index.vue +++ b/src/components/Sticky/index.vue @@ -28,22 +28,22 @@ export default { return { active: false, position: '', - currentTop: '', width: undefined, height: undefined, - child: null, - stickyHeight: 0 + isSticky: false } }, mounted() { this.height = this.$el.getBoundingClientRect().height window.addEventListener('scroll', this.handleScroll) + window.addEventListener('resize', this.handleReize) }, activated() { this.handleScroll() }, destroyed() { window.removeEventListener('scroll', this.handleScroll) + window.removeEventListener('resize', this.handleReize) }, methods: { sticky() { @@ -53,6 +53,7 @@ export default { this.position = 'fixed' this.active = true this.width = this.width + 'px' + this.isSticky = true }, reset() { if (!this.active) { @@ -61,15 +62,21 @@ export default { this.position = '' this.width = 'auto' this.active = false + this.isSticky = false }, handleScroll() { this.width = this.$el.getBoundingClientRect().width const offsetTop = this.$el.getBoundingClientRect().top - if (offsetTop <= this.stickyTop) { + if (offsetTop < this.stickyTop) { this.sticky() return } this.reset() + }, + handleReize() { + if (this.isSticky) { + this.width = this.$el.getBoundingClientRect().width + 'px' + } } } } diff --git a/src/components/Tinymce/components/editorImage.vue b/src/components/Tinymce/components/editorImage.vue index b0347cf8..7569e4f2 100644 --- a/src/components/Tinymce/components/editorImage.vue +++ b/src/components/Tinymce/components/editorImage.vue @@ -1,6 +1,6 @@