更新: 升级开发环境至 vue-cli3; 更新依赖库版本;解决 IE11 下不能正确显示问题;
29个文件已删除
22个文件已修改
6个文件已添加
| | |
| | | |
| | | [预览地址](https://iczer.gitee.io/vue-antd-pro) |
| | | |
| | |  |
| | | ## 重要 |
| | | 该项目目前已升级至 vue-cli3 开发环境,部分依赖组件库版本也已更新至最新版本。 |
| | | vue-cli2 环境代码已封版 [v0.0.1](https://github.com/iczer/vue-antd-admin/tree/0.0.1),如有需要,[点我查看](https://github.com/iczer/vue-antd-admin/tree/0.0.1) |
| | |  |
| | | ## 环境 |
| | | * node -- 运行/编译 |
| | | * yarn -- 依赖管理 |
| | |
| | | * eslint -- 代码规约 |
| | | * vue-cli -- 构建 |
| | | ## 依赖 |
| | | * @antv/data-set: ^0.8.9 |
| | | * ant-design-vue: ^1.0.3 |
| | | * axios: ^0.18.0 |
| | | * clipboard: ^2.0.1 |
| | | * date-fns: ^1.29.0 |
| | | * @antv/data-set: ^0.11.4 |
| | | * ant-design-vue: ^1.6.2 |
| | | * axios: ^0.19.2 |
| | | * clipboard: ^2.0.6 |
| | | * core-js: ^3.6.5, |
| | | * date-fns: ^2.14.0 |
| | | * enquire.js: ^2.1.6 |
| | | * mockjs: ^1.0.1-beta3 |
| | | * pouchdb: ^7.0.0 |
| | | * viser-vue: ^2.2.5 |
| | | * vue: ^2.5.17 |
| | | * vue-router: ^3.0.1 |
| | | * vuedraggable: ^2.16.0 |
| | | * vuex: ^3.0.1 |
| | | * mockjs: ^1.1.0 |
| | | * pouchdb: ^7.2.1 |
| | | * viser-vue: ^2.4.8 |
| | | * vue: ^2.6.11 |
| | | * vue-router: ^3.3.4 |
| | | * vuedraggable: ^2.23.2 |
| | | * vuex: ^3.4.0 |
| | | ## 安装 |
| | | 克隆项目到本地: |
| | | ``` |
| | |
| | | ``` |
| | | ## 启动 |
| | | ``` |
| | | $ yarn start |
| | | $ yarn serve |
| | | ``` |
| | | ## 文档 |
| | | 编写中... |
New file |
| | |
| | | module.exports = { |
| | | presets: [ |
| | | '@vue/cli-plugin-babel/preset' |
| | | ] |
| | | } |
| | |
| | | { |
| | | "name": "vue-antd-admin", |
| | | "version": "1.0.0", |
| | | "description": "A Vue.js project", |
| | | "author": "chenghx <chenghx@nfex.com>", |
| | | "version": "0.1.0", |
| | | "private": true, |
| | | "scripts": { |
| | | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", |
| | | "start": "npm run dev", |
| | | "unit": "jest --config test/unit/jest.conf.js --coverage", |
| | | "e2e": "node test/e2e/runner.js", |
| | | "test": "npm run unit && npm run e2e", |
| | | "lint": "eslint --ext .js,.vue src test/unit test/e2e/specs", |
| | | "build": "node build/build.js" |
| | | "serve": "vue-cli-service serve", |
| | | "build": "vue-cli-service build", |
| | | "lint": "vue-cli-service lint" |
| | | }, |
| | | "dependencies": { |
| | | "@antv/data-set": "^0.8.9", |
| | | "ant-design-vue": "^1.1.1", |
| | | "axios": "^0.18.1", |
| | | "clipboard": "^2.0.1", |
| | | "date-fns": "^1.29.0", |
| | | "@antv/data-set": "^0.11.4", |
| | | "ant-design-vue": "^1.6.2", |
| | | "axios": "^0.19.2", |
| | | "clipboard": "^2.0.6", |
| | | "core-js": "^3.6.5", |
| | | "date-fns": "^2.14.0", |
| | | "enquire.js": "^2.1.6", |
| | | "mockjs": "^1.0.1-beta3", |
| | | "pouchdb": "^7.0.0", |
| | | "viser-vue": "^2.2.5", |
| | | "vue": "^2.6.10", |
| | | "vue-router": "^3.0.1", |
| | | "vuedraggable": "^2.16.0", |
| | | "vuex": "^3.0.1" |
| | | "mockjs": "^1.1.0", |
| | | "pouchdb": "^7.2.1", |
| | | "viser-vue": "^2.4.8", |
| | | "vue": "^2.6.11", |
| | | "vue-router": "^3.3.4", |
| | | "vuedraggable": "^2.23.2", |
| | | "vuex": "^3.4.0" |
| | | }, |
| | | "devDependencies": { |
| | | "autoprefixer": "^7.1.2", |
| | | "babel-core": "^6.22.1", |
| | | "babel-eslint": "^8.2.1", |
| | | "babel-helper-vue-jsx-merge-props": "^2.0.3", |
| | | "babel-jest": "^21.0.2", |
| | | "babel-loader": "^7.1.1", |
| | | "babel-plugin-dynamic-import-node": "^1.2.0", |
| | | "babel-plugin-syntax-jsx": "^6.18.0", |
| | | "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0", |
| | | "babel-plugin-transform-runtime": "^6.22.0", |
| | | "babel-plugin-transform-vue-jsx": "^3.5.0", |
| | | "babel-preset-env": "^1.3.2", |
| | | "babel-preset-stage-2": "^6.22.0", |
| | | "babel-register": "^6.22.0", |
| | | "chalk": "^2.0.1", |
| | | "chromedriver": "^2.27.2", |
| | | "copy-webpack-plugin": "^4.0.1", |
| | | "cross-spawn": "^5.0.1", |
| | | "css-loader": "^0.28.0", |
| | | "eslint": "^4.15.0", |
| | | "eslint-config-standard": "^10.2.1", |
| | | "eslint-friendly-formatter": "^3.0.0", |
| | | "eslint-loader": "^1.7.1", |
| | | "eslint-plugin-import": "^2.7.0", |
| | | "eslint-plugin-node": "^5.2.0", |
| | | "eslint-plugin-promise": "^3.4.0", |
| | | "eslint-plugin-standard": "^3.0.1", |
| | | "eslint-plugin-vue": "^4.0.0", |
| | | "extract-text-webpack-plugin": "^3.0.0", |
| | | "file-loader": "^1.1.4", |
| | | "friendly-errors-webpack-plugin": "^1.6.1", |
| | | "html-webpack-plugin": "^2.30.1", |
| | | "jest": "^22.0.4", |
| | | "jest-serializer-vue": "^0.3.0", |
| | | "less": "^3.7.1", |
| | | "less-loader": "^4.1.0", |
| | | "nightwatch": "^0.9.12", |
| | | "node-notifier": "^5.1.2", |
| | | "optimize-css-assets-webpack-plugin": "^3.2.0", |
| | | "ora": "^1.2.0", |
| | | "portfinder": "^1.0.13", |
| | | "postcss-import": "^11.0.0", |
| | | "postcss-loader": "^2.0.8", |
| | | "postcss-url": "^7.2.1", |
| | | "rimraf": "^2.6.0", |
| | | "selenium-server": "^3.0.1", |
| | | "semver": "^5.3.0", |
| | | "shelljs": "^0.7.6", |
| | | "uglifyjs-webpack-plugin": "^1.1.1", |
| | | "url-loader": "^0.5.8", |
| | | "vue-jest": "^1.0.2", |
| | | "vue-loader": "^13.3.0", |
| | | "vue-style-loader": "^3.0.1", |
| | | "vue-template-compiler": "^2.6.10", |
| | | "webpack": "^3.6.0", |
| | | "webpack-bundle-analyzer": "^3.3.2", |
| | | "webpack-dev-server": "^2.9.1", |
| | | "webpack-merge": "^4.1.0" |
| | | "@vue/cli-plugin-babel": "^4.4.0", |
| | | "@vue/cli-plugin-eslint": "^4.4.0", |
| | | "@vue/cli-service": "^4.4.0", |
| | | "babel-eslint": "^10.1.0", |
| | | "babel-polyfill": "^6.26.0", |
| | | "eslint": "^6.7.2", |
| | | "eslint-plugin-vue": "^6.2.2", |
| | | "less-loader": "^6.1.1", |
| | | "style-resources-loader": "^1.3.2", |
| | | "vue-cli-plugin-style-resources-loader": "^0.1.4", |
| | | "vue-template-compiler": "^2.6.11", |
| | | "whatwg-fetch": "^3.0.0" |
| | | }, |
| | | "engines": { |
| | | "node": ">= 6.0.0", |
| | | "npm": ">= 3.0.0" |
| | | "eslintConfig": { |
| | | "root": true, |
| | | "env": { |
| | | "node": true |
| | | }, |
| | | "extends": [ |
| | | "plugin:vue/essential", |
| | | "eslint:recommended" |
| | | ], |
| | | "parserOptions": { |
| | | "parser": "babel-eslint" |
| | | }, |
| | | "rules": {} |
| | | }, |
| | | "browserslist": [ |
| | | "> 1%", |
| | | "last 2 versions", |
| | | "not ie <= 8" |
| | | "ie 8" |
| | | ] |
| | | } |
New file |
| | |
| | | <!DOCTYPE html> |
| | | <html lang="en"> |
| | | <head> |
| | | <meta charset="utf-8"> |
| | | <meta http-equiv="X-UA-Compatible" content="IE=edge"> |
| | | <meta name="viewport" content="width=device-width,initial-scale=1.0"> |
| | | <link rel="icon" href="<%= BASE_URL %>favicon.ico"> |
| | | <title><%= htmlWebpackPlugin.options.title %></title> |
| | | </head> |
| | | <body> |
| | | <noscript> |
| | | <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> |
| | | </noscript> |
| | | <div id="app"></div> |
| | | <!-- built files will be auto injected --> |
| | | </body> |
| | | </html> |
| | |
| | | :dataSource="searchData" |
| | | :columns="columns" size="small" |
| | | :pagination="{style: { marginBottom: 0 }, pageSize: 5}" |
| | | rowKey="index" |
| | | > |
| | | <a href="#/" slot="keyword" slot-scope="text">{{text}}</a> |
| | | <span slot="rang" slot-scope="text">{{text}} %<a-icon type="caret-up" /> </span> |
| | |
| | | const fakeY = [7, 5, 4, 2, 4, 7, 5, 6, 5, 9, 6, 3, 1, 5, 3, 6, 5] |
| | | for (let i = 0; i < fakeY.length; i += 1) { |
| | | data.push({ |
| | | x: format(new Date(beginDay + 1000 * 60 * 60 * 24 * i), 'YYYY-MM-DD'), |
| | | x: format(new Date(beginDay + 1000 * 60 * 60 * 24 * i), 'yyyy-MM-dd'), |
| | | y: fakeY[i] |
| | | }) |
| | | } |
| | |
| | | const fakeY = [7, 5, 4, 2, 4, 7, 5, 6, 5, 9, 6, 3, 1, 5, 3, 6, 5] |
| | | for (let i = 0; i < fakeY.length; i += 1) { |
| | | data.push({ |
| | | x: format(new Date(beginDay + 1000 * 60 * 60 * 24 * i), 'YYYY-MM-DD'), |
| | | x: format(new Date(beginDay + 1000 * 60 * 60 * 24 * i), 'yyyy-MM-dd'), |
| | | y: fakeY[i] |
| | | }) |
| | | } |
| | |
| | | }, |
| | | inject: ['groupContext'], |
| | | watch: { |
| | | 'sChecked': function (val) { |
| | | 'sChecked': function () { |
| | | const value = { |
| | | value: this.value, |
| | | color: this.color, |
| | |
| | | }, |
| | | inject: ['groupContext'], |
| | | watch: { |
| | | 'sChecked': function (val) { |
| | | 'sChecked': function () { |
| | | const option = { |
| | | value: this.value, |
| | | checked: this.sChecked |
| | |
| | | <a-layout-sider :class="[theme, 'sider', isMobile ? null : 'shadow']" width="256px" :collapsible="collapsible" v-model="collapsed" :trigger="null"> |
| | | <div :class="['logo', theme]"> |
| | | <router-link to="/dashboard/workplace"> |
| | | <img src="static/img/vue-antd-logo.png"> |
| | | <img src="@/assets/img/vue-antd-logo.png"> |
| | | <h1>{{systemName}}</h1> |
| | | </router-link> |
| | | </div> |
| | |
| | | }, |
| | | [ |
| | | h( |
| | | 'a', |
| | | {attrs: {href: '#' + menu.path}}, |
| | | 'RouterLink', |
| | | // {attrs: {href: '#' + menu.path}}, |
| | | {attrs: {to: menu.path}}, |
| | | [ |
| | | this.renderIcon(h, menu.icon), |
| | | h('span', [menu.name]) |
| | |
| | | |
| | | <script> |
| | | import SettingItem from './SettingItem' |
| | | import StyleItem from './StyleItem' |
| | | import ColorCheckbox from '../checkbox/ColorCheckbox' |
| | | import ImgCheckbox from '../checkbox/ImgCheckbox' |
| | | import Clipboard from 'clipboard' |
| | |
| | | |
| | | export default { |
| | | name: 'Setting', |
| | | components: {ImgCheckboxGroup, ImgCheckbox, ColorCheckboxGroup, ColorCheckbox, StyleItem, SettingItem}, |
| | | components: {ImgCheckboxGroup, ImgCheckbox, ColorCheckboxGroup, ColorCheckbox, SettingItem}, |
| | | computed: { |
| | | multipage () { |
| | | return this.$store.state.setting.multipage |
| | |
| | | <a-alert type="info" :show-icon="true"> |
| | | <div slot="message"> |
| | | 已选择 <a style="font-weight: 600">{{selectedRows.length}}</a> 项 |
| | | <template v-for="(item, index) in needTotalList" v-if="item.needTotal"> |
| | | {{item.title}}总计 |
| | | <a :key="index" style="font-weight: 600"> |
| | | {{item.customRender ? item.customRender(item.total) : item.total}} |
| | | </a> |
| | | </template> |
| | | <div v-for="(item, index) in needTotalList" :key="index"> |
| | | <div v-if="item.needTotal"> |
| | | {{item.title}}总计 |
| | | <a :key="index" style="font-weight: 600"> |
| | | {{item.customRender ? item.customRender(item.total) : item.total}} |
| | | </a> |
| | | </div> |
| | | </div> |
| | | <a style="margin-left: 24px">清空</a> |
| | | </div> |
| | | </a-alert> |
| | |
| | | <div > |
| | | <div :class="['mask', openDrawer ? 'open' : 'close']" @click="close"></div> |
| | | <div :class="['drawer', placement, openDrawer ? 'open' : 'close']"> |
| | | <div ref="drawer" style="position: relative; height: 100%;"> |
| | | <div ref="drawer" class="content"> |
| | | <slot></slot> |
| | | </div> |
| | | <div v-if="showHandler" :class="['handler-container', placement]" ref="handler" @click="handle"> |
| | | <div v-if="showHandler" :class="['handler-container', placement, openDrawer ? 'open' : 'close']" ref="handler" @click="handle"> |
| | | <slot v-if="$slots.handler" name="handler"></slot> |
| | | <div v-else class="handler"> |
| | | <a-icon :type="openDrawer ? 'close' : 'bars'" /> |
| | |
| | | this.drawerWidth = this.getDrawerWidth() |
| | | }, |
| | | watch: { |
| | | 'drawerWidth': function (val) { |
| | | 'drawerWidth': function () { |
| | | if (this.placement === 'left') { |
| | | this.$refs.handler.style.left = val + 'px' |
| | | //this.$refs.handler.style.left = val + 'px' |
| | | } else { |
| | | this.$refs.handler.style.right = val + 'px' |
| | | //this.$refs.handler.style.right = val + 'px' |
| | | } |
| | | } |
| | | }, |
| | |
| | | &.left{ |
| | | left: 0px; |
| | | &.open{ |
| | | box-shadow: 2px 0 8px rgba(0,0,0,.15); |
| | | .content{ |
| | | box-shadow: 2px 0 8px rgba(0,0,0,.15); |
| | | } |
| | | } |
| | | &.close{ |
| | | transform: translateX(-100%); |
| | | transform: translateX(-100%) translateX(40px); |
| | | } |
| | | } |
| | | &.right{ |
| | | right: 0px; |
| | | .content{ |
| | | float: right; |
| | | } |
| | | &.open{ |
| | | box-shadow: -2px 0 8px rgba(0,0,0,.15); |
| | | .content{ |
| | | box-shadow: -2px 0 8px rgba(0,0,0,.15); |
| | | } |
| | | } |
| | | &.close{ |
| | | transform: translateX(100%); |
| | | transform: translateX(100%) translateX(-40px); |
| | | } |
| | | } |
| | | .sider{ |
| | | height: 100%; |
| | | } |
| | | } |
| | | .content{ |
| | | display: inline-block; |
| | | height: 100%; |
| | | } |
| | | .handler-container{ |
| | | position: fixed; |
| | | top: 200px; |
| | | display: inline-block; |
| | | text-align: center; |
| | | transition: all 0.5s; |
| | | cursor: pointer; |
| | | vertical-align: top; |
| | | margin-top: 200px; |
| | | z-index: 100; |
| | | .handler { |
| | | height: 40px; |
| | | width: 40px; |
| | | background-color: #fff; |
| | | z-index: 100; |
| | | font-size: 26px; |
| | | box-shadow: 2px 0 8px rgba(0, 0, 0, 0.15); |
| | | line-height: 40px; |
| | |
| | | <a-layout-header :class="[theme, 'global-header']"> |
| | | <div :class="['global-header-wide', layout]"> |
| | | <router-link v-if="isMobile || layout === 'head'" to="/" :class="['logo', isMobile ? null : 'pc', theme]"> |
| | | <img width="32" src="static/img/vue-antd-logo.png" /> |
| | | <img width="32" src="@/assets/img/vue-antd-logo.png" /> |
| | | <h1 v-if="!isMobile">{{systemName}}</h1> |
| | | </router-link> |
| | | <a-divider v-if="isMobile" type="vertical" /> |
| | |
| | | this.activePage = this.$route.fullPath |
| | | }, |
| | | watch: { |
| | | '$route': function (newRoute, oldRoute) { |
| | | '$route': function (newRoute) { |
| | | this.activePage = newRoute.fullPath |
| | | if (!this.multipage) { |
| | | this.linkList = [newRoute.fullPath] |
| | |
| | | 'activePage': function (key) { |
| | | this.$router.push(key) |
| | | }, |
| | | 'multipage': function (newVal, oldVal) { |
| | | 'multipage': function (newVal) { |
| | | if (!newVal) { |
| | | this.linkList = [this.$route.fullPath] |
| | | this.pageList = [this.$route] |
| | |
| | | </template> |
| | | </div> |
| | | </div> |
| | | <slot slot="extra" name="extra"></slot> |
| | | <slot v-if="this.$refs.extra" slot="extra" name="extra"></slot> |
| | | </page-header> |
| | | <div ref="page" :class="['page-content', layout]" > |
| | | <slot ></slot> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import PageHeader from '../components/page/PageHeader' |
| | | import PageLayout from './PageLayout' |
| | | export default { |
| | | name: 'PageView', |
| | | components: {PageLayout, PageHeader}, |
| | | components: {PageLayout}, |
| | | data () { |
| | | return { |
| | | title: '', |
| | |
| | | // The Vue build version to load with the `import` command |
| | | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. |
| | | import Vue from 'vue' |
| | | import App from './App' |
| | | import App from './App.vue' |
| | | import router from './router/lazy' |
| | | import 'ant-design-vue/dist/antd.css' |
| | | import Antd from 'ant-design-vue' |
| | |
| | | Vue.use(Viser) |
| | | Vue.use(Antd) |
| | | |
| | | /* eslint-disable no-new */ |
| | | new Vue({ |
| | | el: '#app', |
| | | router, |
| | | store, |
| | | components: { App }, |
| | | template: '<App/>', |
| | | render: h => h(App), |
| | | mounted () { |
| | | var db = new PouchDB('admindb') |
| | | db.get('currUser').then(doc => { |
| | | this.$store.commit('account/setuser', doc.user) |
| | | }) |
| | | } |
| | | }) |
| | | }, |
| | | }).$mount('#app') |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import PageHeader from '../../components/page/PageHeader' |
| | | import PageLayout from '../../layouts/PageLayout' |
| | | import HeadInfo from '../../components/tool/HeadInfo' |
| | | import Radar from '../../components/chart/Radar' |
| | | |
| | | export default { |
| | | name: 'WorkPlace', |
| | | components: {Radar, HeadInfo, PageLayout, PageHeader}, |
| | | components: {Radar, HeadInfo, PageLayout}, |
| | | data () { |
| | | return { |
| | | projects: [], |
| | |
| | | :dataSource="dataSource" |
| | | :pagination="false" |
| | | > |
| | | <template v-for="(col, i) in ['name', 'workId', 'department']" :slot="col" slot-scope="text, record, index"> |
| | | <template v-for="(col, i) in ['name', 'workId', 'department']" :slot="col" slot-scope="text, record"> |
| | | <a-input |
| | | :key="col" |
| | | v-if="record.editable" |
| | |
| | | /> |
| | | <template v-else>{{text}}</template> |
| | | </template> |
| | | <template slot="operation" slot-scope="text, record, index"> |
| | | <template slot="operation" slot-scope="text, record"> |
| | | <template v-if="record.editable"> |
| | | <span v-if="record.isNew"> |
| | | <a @click="saveRow(record.key)">添加</a> |
| | |
| | | :grid="{gutter: 24, lg: 3, md: 2, sm: 1, xs: 1}" |
| | | :dataSource="dataSource" |
| | | > |
| | | <a-list-item slot="renderItem" slot-scope="item, index"> |
| | | <template v-if="item === null"> |
| | | <a-list-item slot="renderItem" slot-scope="item"> |
| | | <template v-if="item.add"> |
| | | <a-button class="new-btn" type="dashed"> |
| | | <a-icon type="plus" />新增产品 |
| | | </a-button> |
| | |
| | | |
| | | <script> |
| | | const dataSource = [] |
| | | dataSource.push(null) |
| | | dataSource.push({ |
| | | add: true |
| | | }) |
| | | for (let i = 0; i < 11; i++) { |
| | | dataSource.push({ |
| | | title: 'Alipay', |
| | |
| | | background-color: #fff; |
| | | border-radius: 2px; |
| | | width: 100%; |
| | | height: 188px; |
| | | height: 187px; |
| | | } |
| | | .meta-content{ |
| | | position: relative; |
| | |
| | | <div class="content"> |
| | | <div class="top"> |
| | | <div class="header"> |
| | | <img alt="logo" class="logo" src="static/img/vue-antd-logo.png" /> |
| | | <img alt="logo" class="logo" src="@/assets/img/vue-antd-logo.png" /> |
| | | <span class="title">{{systemName}}</span> |
| | | </div> |
| | | <div class="desc">Ant Design 是西湖区最具影响力的 Web 设计规范</div> |
| | |
| | | methods: { |
| | | onSubmit (e) { |
| | | e.preventDefault() |
| | | this.form.validateFields((err, values) => { |
| | | this.form.validateFields((err) => { |
| | | if (!err) { |
| | | this.logging = true |
| | | this.$axios.post('/login', { |
New file |
| | |
| | | module.exports = { |
| | | pluginOptions: { |
| | | 'style-resources-loader': { |
| | | preProcessor: 'less', |
| | | patterns: [] |
| | | } |
| | | }, |
| | | configureWebpack: config => { |
| | | config.entry.app = ["babel-polyfill", "whatwg-fetch", "./src/main.js"]; |
| | | } |
| | | } |