Compare commits
151 Commits
v4.0.0
...
v4.0.0-bet
Author | SHA1 | Date | |
---|---|---|---|
|
3a796471c3 | ||
|
387b206199 | ||
|
b9fd5ae6d3 | ||
|
297959083c | ||
|
5e3ae144b3 | ||
|
c48777ff2d | ||
|
3c0415c86d | ||
|
58a66d4902 | ||
|
960b562e84 | ||
|
ea0602a50f | ||
|
896b7369bf | ||
|
a9b4467472 | ||
|
74b6bb8069 | ||
|
ec7c585813 | ||
|
d919acf64b | ||
|
3594052c90 | ||
|
d1b786946c | ||
|
59b1493579 | ||
|
0c6e45e9a1 | ||
|
e1d61898ed | ||
|
fef9fda685 | ||
|
0c50029cf7 | ||
|
7c33568883 | ||
|
d927d4172f | ||
|
fd4b5c4052 | ||
|
a2b9b37c9c | ||
|
9665307220 | ||
|
27322ac4d3 | ||
|
6c6f03f664 | ||
|
8b382e1e15 | ||
|
c93d88a348 | ||
|
686d0acd6d | ||
|
05ca5cae6d | ||
|
f3aefe54e8 | ||
|
a80999e0a2 | ||
|
4b5b0a6e6b | ||
|
3d973f7ddd | ||
|
b44335f012 | ||
|
f175427a61 | ||
|
183249a5d4 | ||
|
87272fd62d | ||
|
b0e3dc8617 | ||
|
e855f6a121 | ||
|
537ecf9990 | ||
|
dedf8e7ced | ||
|
6c1c03c828 | ||
|
20fdb5cd8b | ||
|
60b4549bf5 | ||
|
6b74a4ec72 | ||
|
1d3683a8c8 | ||
|
66e8ca9cec | ||
|
653de1f31e | ||
|
1dfea3b287 | ||
|
2ac4cee805 | ||
|
94a3d7be7e | ||
|
3560fcacf9 | ||
|
8e0b5624a9 | ||
|
44e4d3d005 | ||
|
fef2853951 | ||
|
f8f7667ab1 | ||
|
5508f05132 | ||
|
cbc77c9a93 | ||
|
583e96cca5 | ||
|
6d9ac37662 | ||
|
9a5827ca8a | ||
|
c44d001df6 | ||
|
8029c076b9 | ||
|
d45e80549f | ||
|
0bc681efe6 | ||
|
0f3d2bcd05 | ||
|
2d8a238880 | ||
|
30d4d85b34 | ||
|
5224a00ddc | ||
|
054e9c4a73 | ||
|
041075633f | ||
|
d955fe8b0f | ||
|
e0991da9cf | ||
|
a9fd6e2919 | ||
|
3cba7b52da | ||
|
32b747014d | ||
|
8e047596b1 | ||
|
172d6a1d08 | ||
|
abc8ce21f4 | ||
|
e574ca0331 | ||
|
1e5d2c0ed2 | ||
|
56bd080b54 | ||
|
87f1bbdb7b | ||
|
bea356ac70 | ||
|
ce35a6f744 | ||
|
6363eb627d | ||
|
0f6946a88e | ||
|
22cdfc246c | ||
|
2d275a9891 | ||
|
93c13d2cea | ||
|
78e8888389 | ||
|
bb50a7422d | ||
|
4afb57a1e5 | ||
|
3af14bc297 | ||
|
0bf8b5960d | ||
|
bae3601606 | ||
|
77113a0cb2 | ||
|
1cd1ef690c | ||
|
4e9f08e639 | ||
|
94ed283c51 | ||
|
67c06022e1 | ||
|
d3904e6c28 | ||
|
5a1fa14753 | ||
|
cff015f5d6 | ||
|
3a2da6afd3 | ||
|
a92151d048 | ||
|
9ce0f81d5f | ||
|
49f1e5e6dc | ||
|
b8b787733c | ||
|
075d29acea | ||
|
84b19d7283 | ||
|
2f731000c1 | ||
|
a6c8e1a11a | ||
|
929a4fc0c8 | ||
|
8836133f66 | ||
|
5849b13d3f | ||
|
5f343ec9e4 | ||
|
05b28e20bd | ||
|
8cb6983550 | ||
|
f0f8363cf7 | ||
|
6f5591c290 | ||
|
5c23accd9e | ||
|
14ece5ba9b | ||
|
cfdff383db | ||
|
8921752441 | ||
|
8e5b142c36 | ||
|
4b916c8e4d | ||
|
889771fa7a | ||
|
21516170a9 | ||
|
da286d4439 | ||
|
51f99770fe | ||
|
aefd8bb36a | ||
|
40a7626acb | ||
|
6c967f177a | ||
|
c042dc8de3 | ||
|
f79d0febb1 | ||
|
10031547ec | ||
|
ccc90502ce | ||
|
6f0c40e841 | ||
|
2ba5f25205 | ||
|
b9eedb8689 | ||
|
a67b455306 | ||
|
27772946c2 | ||
|
4cdcbee0d6 | ||
|
97261a2feb | ||
|
0f7cf7e820 | ||
|
3802f6f8d2 |
@@ -1,14 +1,9 @@
|
|||||||
# just a flag
|
VUE_APP_BASE_API = '/api'
|
||||||
ENV = 'development'
|
ENV = 'development'
|
||||||
|
|
||||||
# base api
|
// With this configuration, vue-cli uses babel-plugin-dynamic-import-node
|
||||||
VUE_APP_BASE_API = '/dev-api'
|
// It only does one thing by converting all import() to require()
|
||||||
|
// So that all asynchronous components can be import synchronously using this plugin
|
||||||
# vue-cli uses the VUE_CLI_BABEL_TRANSPILE_MODULES environment variable,
|
// This configuration can significantly increase the speed of hot updates when you have a large number of pages
|
||||||
# to control whether the babel-plugin-dynamic-import-node plugin is enabled.
|
// https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/babel-preset-app/index.js
|
||||||
# It only does one thing by converting all import() to require().
|
|
||||||
# This configuration can significantly increase the speed of hot updates,
|
|
||||||
# when you have a large number of pages.
|
|
||||||
# Detail: https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/babel-preset-app/index.js
|
|
||||||
|
|
||||||
VUE_CLI_BABEL_TRANSPILE_MODULES = true
|
VUE_CLI_BABEL_TRANSPILE_MODULES = true
|
||||||
|
@@ -1,6 +1,2 @@
|
|||||||
# just a flag
|
VUE_APP_BASE_API = '/api'
|
||||||
ENV = 'production'
|
ENV = 'production'
|
||||||
|
|
||||||
# base api
|
|
||||||
VUE_APP_BASE_API = '/prod-api'
|
|
||||||
|
|
||||||
|
@@ -1,8 +1,3 @@
|
|||||||
NODE_ENV = production
|
NODE_ENV=production
|
||||||
|
VUE_APP_BASE_API = '/api'
|
||||||
# just a flag
|
|
||||||
ENV = 'staging'
|
ENV = 'staging'
|
||||||
|
|
||||||
# base api
|
|
||||||
VUE_APP_BASE_API = '/stage-api'
|
|
||||||
|
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
build/*.js
|
build/*.js
|
||||||
|
config/*.js
|
||||||
src/assets
|
src/assets
|
||||||
public
|
|
||||||
dist
|
|
||||||
|
49
README.md
49
README.md
@@ -4,10 +4,10 @@
|
|||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/vuejs/vue">
|
<a href="https://github.com/vuejs/vue">
|
||||||
<img src="https://img.shields.io/badge/vue-2.6.10-brightgreen.svg" alt="vue">
|
<img src="https://img.shields.io/badge/vue-2.5.17-brightgreen.svg" alt="vue">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/ElemeFE/element">
|
<a href="https://github.com/ElemeFE/element">
|
||||||
<img src="https://img.shields.io/badge/element--ui-2.7.0-brightgreen.svg" alt="element-ui">
|
<img src="https://img.shields.io/badge/element--ui-2.4.11-brightgreen.svg" alt="element-ui">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://travis-ci.org/PanJiaChen/vue-element-admin" rel="nofollow">
|
<a href="https://travis-ci.org/PanJiaChen/vue-element-admin" rel="nofollow">
|
||||||
<img src="https://travis-ci.org/PanJiaChen/vue-element-admin.svg?branch=master" alt="Build Status">
|
<img src="https://travis-ci.org/PanJiaChen/vue-element-admin.svg?branch=master" alt="Build Status">
|
||||||
@@ -30,7 +30,7 @@ English | [简体中文](./README.zh-CN.md)
|
|||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
[vue-element-admin](http://panjiachen.github.io/vue-element-admin) is a production-ready front-end solution for admin interfaces. It based on [vue](https://github.com/vuejs/vue) and use the UI Toolkit [element-ui](https://github.com/ElemeFE/element).
|
[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.
|
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.
|
||||||
|
|
||||||
@@ -40,31 +40,36 @@ It is a magical vue admin based on the newest development stack of vue, built-in
|
|||||||
|
|
||||||
- [Gitter](https://gitter.im/vue-element-admin/discuss)
|
- [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)
|
- [Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
|
||||||
|
|
||||||
|
- [Donate](https://panjiachen.github.io/vue-element-admin-site/donate/)
|
||||||
|
|
||||||
- [Gitee](https://panjiachen.gitee.io/vue-element-admin/) 国内用户可访问该地址在线预览
|
- [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: [vue-admin-template](https://github.com/PanJiaChen/vue-admin-template)
|
- Base template recommends using: [vue-admin-template](https://github.com/PanJiaChen/vue-admin-template)
|
||||||
- Desktop: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
|
- Desktop: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
|
||||||
- Typescript: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (Credits: [@Armour](https://github.com/Armour))
|
- Typescript: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (Credits: [@Armour](https://github.com/Armour))
|
||||||
|
|
||||||
**The current version is `4.0-beta`. If you find a problem, please put [issue](https://github.com/PanJiaChen/vue-element-admin/issues/new). If you want to use the old version - stable version, you can switch branch to [tag/3.11.0](https://github.com/PanJiaChen/vue-element-admin/tree/tag/3.11.0)**
|
**This project does not support low version browsers (e.g. IE). Please add polyfill yourself if you need them.**
|
||||||
|
|
||||||
**This project does not support low version browsers (e.g. IE). Please add polyfill by yourself.**
|
**Note: This project uses element-ui@2.3.0+ version, so the minimum compatible vue@2.5.0+**
|
||||||
|
|
||||||
|
**Start using `webpack4` from `v3.8.0`. If you still want to continue using `webpack3`, please use this branch [webpack3](https://github.com/PanJiaChen/vue-element-admin/tree/webpack3)**
|
||||||
|
|
||||||
## Preparation
|
## 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/), [vue-cli](https://github.com/vuejs/vue-cli) , [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).
|
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.
|
Understanding and learning this knowledge in advance will greatly help the use of this project.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img width="900" src="https://wpimg.wallstcn.com/a5894c1b-f6af-456e-82df-1151da0839bf.png">
|
<img width="900" src="https://wpimg.wallstcn.com/a5894c1b-f6af-456e-82df-1151da0839bf.png">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## Sponsors
|
## Sponsors
|
||||||
|
|
||||||
Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor]](https://www.patreon.com/panjiachen)
|
Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor]](https://www.patreon.com/panjiachen)
|
||||||
|
|
||||||
<a href="https://flatlogic.com/admin-dashboards?from=vue-element-admin"><img width="150px" src="https://wpimg.wallstcn.com/9c0b719b-5551-4c1e-b776-63994632d94a.png" /></a><p>Admin Dashboard Templates made with Vue, React and Angular.</p>
|
<a href="https://flatlogic.com/admin-dashboards?from=vue-element-admin"><img width="150px" src="https://wpimg.wallstcn.com/9c0b719b-5551-4c1e-b776-63994632d94a.png" /></a><p>Admin Dashboard Templates made with Vue, React and Angular.</p>
|
||||||
@@ -77,7 +82,6 @@ Become a sponsor and get your logo on our README on GitHub with a link to your s
|
|||||||
- Permission Authentication
|
- Permission Authentication
|
||||||
- Page permission
|
- Page permission
|
||||||
- Directive permission
|
- Directive permission
|
||||||
- Permission configuration page
|
|
||||||
- Two-step login
|
- Two-step login
|
||||||
|
|
||||||
- Multi-environment build
|
- Multi-environment build
|
||||||
@@ -101,13 +105,14 @@ Become a sponsor and get your logo on our README on GitHub with a link to your s
|
|||||||
|
|
||||||
- Excel
|
- Excel
|
||||||
- Export Excel
|
- Export Excel
|
||||||
|
- Export zip
|
||||||
- Upload Excel
|
- Upload Excel
|
||||||
- Visualization Excel
|
- Visualization Excel
|
||||||
- Export zip
|
|
||||||
|
|
||||||
- Table
|
- Table
|
||||||
- Dynamic Table
|
- Dynamic Table
|
||||||
- Drag And Drop Table
|
- Drag And Drop Table
|
||||||
|
- Tree Table
|
||||||
- Inline Edit Table
|
- Inline Edit Table
|
||||||
|
|
||||||
- Error Page
|
- Error Page
|
||||||
@@ -141,9 +146,6 @@ Become a sponsor and get your logo on our README on GitHub with a link to your s
|
|||||||
# clone the project
|
# clone the project
|
||||||
git clone https://github.com/PanJiaChen/vue-element-admin.git
|
git clone https://github.com/PanJiaChen/vue-element-admin.git
|
||||||
|
|
||||||
# enter the project directory
|
|
||||||
cd vue-element-admin
|
|
||||||
|
|
||||||
# install dependency
|
# install dependency
|
||||||
npm install
|
npm install
|
||||||
|
|
||||||
@@ -151,13 +153,13 @@ npm install
|
|||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
This will automatically open http://localhost:9527
|
This will automatically open http://localhost:9527.
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# build for test environment
|
# build for test environment
|
||||||
npm run build:stage
|
npm run build:sit
|
||||||
|
|
||||||
# build for production environment
|
# build for production environment
|
||||||
npm run build:prod
|
npm run build:prod
|
||||||
@@ -166,16 +168,19 @@ npm run build:prod
|
|||||||
## Advanced
|
## Advanced
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# preview the release environment effect
|
# --report to build with bundle size analytics
|
||||||
npm run preview
|
npm run build:prod --report
|
||||||
|
|
||||||
# preview the release environment effect + static resource analysis
|
# --generate a bundle size analytics. default: bundle-report.html
|
||||||
npm run preview -- --report
|
npm run build:prod --generate_report
|
||||||
|
|
||||||
# code format check
|
# --preview to start a server in local to preview
|
||||||
|
npm run build:prod --preview
|
||||||
|
|
||||||
|
# lint code
|
||||||
npm run lint
|
npm run lint
|
||||||
|
|
||||||
# code format check and auto fix
|
# auto fix
|
||||||
npm run lint -- --fix
|
npm run lint -- --fix
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@@ -4,10 +4,10 @@
|
|||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/vuejs/vue">
|
<a href="https://github.com/vuejs/vue">
|
||||||
<img src="https://img.shields.io/badge/vue-2.6.10-brightgreen.svg" alt="vue">
|
<img src="https://img.shields.io/badge/vue-2.5.10-brightgreen.svg" alt="vue">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/ElemeFE/element">
|
<a href="https://github.com/ElemeFE/element">
|
||||||
<img src="https://img.shields.io/badge/element--ui-2.7.0-brightgreen.svg" alt="element-ui">
|
<img src="https://img.shields.io/badge/element--ui-2.4.11-brightgreen.svg" alt="element-ui">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://travis-ci.org/PanJiaChen/vue-element-admin" rel="nofollow">
|
<a href="https://travis-ci.org/PanJiaChen/vue-element-admin" rel="nofollow">
|
||||||
<img src="https://travis-ci.org/PanJiaChen/vue-element-admin.svg?branch=master" alt="Build Status">
|
<img src="https://travis-ci.org/PanJiaChen/vue-element-admin.svg?branch=master" alt="Build Status">
|
||||||
@@ -30,37 +30,41 @@
|
|||||||
|
|
||||||
## 简介
|
## 简介
|
||||||
|
|
||||||
[vue-element-admin](http://panjiachen.github.io/vue-element-admin) 是一个后台前端解决方案,它基于 [vue](https://github.com/vuejs/vue) 和 [element-ui](https://github.com/ElemeFE/element)实现。它使用了最新的前端技术栈,内置了 i18n 国际化解决方案,动态路由,权限验证,提炼了典型的业务模型,提供了丰富的功能组件,它可以帮助你快速搭建企业级中后台产品原型。相信不管你的需求是什么,本项目都能帮助到你。
|
[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)
|
- [在线访问](http://panjiachen.github.io/vue-element-admin)
|
||||||
|
|
||||||
- [使用文档](https://panjiachen.github.io/vue-element-admin-site/zh/)
|
- [使用文档](https://panjiachen.github.io/vue-element-admin-site/zh/)
|
||||||
|
|
||||||
- [Gitter 讨论组](https://gitter.im/vue-element-admin/discuss)
|
- [Gitter 讨论组](https://gitter.im/vue-element-admin/discuss)
|
||||||
|
|
||||||
- [Donate](https://panjiachen.gitee.io/vue-element-admin-site/zh/donate)
|
|
||||||
|
|
||||||
- [Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
|
- [Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
|
||||||
|
|
||||||
- [Gitee](https://panjiachen.gitee.io/vue-element-admin/) 在线预览(国内用户可访问该地址)
|
- [Donate](https://panjiachen.gitee.io/vue-element-admin-site/zh/donate)
|
||||||
|
|
||||||
- [国内访问文档](https://panjiachen.gitee.io/vue-element-admin-site/zh/) 文档(方便没翻墙的用户查看)
|
- [Gitee](https://panjiachen.gitee.io/vue-element-admin/) 国内用户可访问该地址在线预览
|
||||||
|
|
||||||
- 基础模板建议使用: [vue-admin-template](https://github.com/PanJiaChen/vue-admin-template)
|
- [国内访问文档](https://panjiachen.gitee.io/vue-element-admin-site/zh/) 方便没翻墙的用户查看文档
|
||||||
|
|
||||||
|
**本项目的定位是后台集成方案,不适合当基础模板来开发。**
|
||||||
|
|
||||||
|
- 模板建议使用: [vue-admin-template](https://github.com/PanJiaChen/vue-admin-template)
|
||||||
- 桌面端: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
|
- 桌面端: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
|
||||||
- Typescript 版: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (鸣谢: [@Armour](https://github.com/Armour))
|
- Typescript版: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (鸣谢: [@Armour](https://github.com/Armour))
|
||||||
|
|
||||||
**目前版本为 `4.0-beta`,若发现问题,欢迎提[issue](https://github.com/PanJiaChen/vue-element-admin/issues/new)。若你想使用旧版本-稳定版,可以切换分支到[tag/3.11.0](https://github.com/PanJiaChen/vue-element-admin/tree/tag/3.11.0)**
|
群主 **[圈子](https://jianshiapp.com/circles/1209)** 楼主会经常分享一些技术相关的东西,或者加入[qq 群](https://github.com/PanJiaChen/vue-element-admin/issues/602)
|
||||||
|
|
||||||
|
**注意:该项目使用 element-ui@2.3.0+ 版本,所以最低兼容 vue@2.5.0+**
|
||||||
|
|
||||||
|
**从`v3.8.0`开始使用`webpack4`。所以若还想使用`webpack3`开发,请使用该分支[webpack3](https://github.com/PanJiaChen/vue-element-admin/tree/webpack3)**
|
||||||
|
|
||||||
**该项目不支持低版本浏览器(如 ie),有需求请自行添加 polyfill [详情](https://github.com/PanJiaChen/vue-element-admin/wiki#babel-polyfill)**
|
**该项目不支持低版本浏览器(如 ie),有需求请自行添加 polyfill [详情](https://github.com/PanJiaChen/vue-element-admin/wiki#babel-polyfill)**
|
||||||
|
|
||||||
群主 **[圈子](https://jianshiapp.com/circles/1209)** 群主会经常分享一些技术相关的东西,或者加入 [qq 群](https://github.com/PanJiaChen/vue-element-admin/issues/602) 或者关注 [微博](https://weibo.com/u/3423485724?is_all=1)
|
|
||||||
|
|
||||||
## 前序准备
|
## 前序准备
|
||||||
|
|
||||||
你需要在本地安装 [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/) 、[vue-cli](https://github.com/vuejs/vue-cli) 、[axios](https://github.com/axios/axios) 和 [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)
|
- [手摸手,带你用 vue 撸后台 系列一(基础篇)](https://juejin.im/post/59097cd7a22b9d0065fb61d2)
|
||||||
- [手摸手,带你用 vue 撸后台 系列二(登录权限篇)](https://juejin.im/post/591aa14f570c35006961acac)
|
- [手摸手,带你用 vue 撸后台 系列二(登录权限篇)](https://juejin.im/post/591aa14f570c35006961acac)
|
||||||
@@ -78,7 +82,6 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
## Sponsors
|
## Sponsors
|
||||||
|
|
||||||
Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor]](https://www.patreon.com/panjiachen)
|
Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor]](https://www.patreon.com/panjiachen)
|
||||||
|
|
||||||
<a href="https://flatlogic.com/admin-dashboards?from=vue-element-admin"><img width="150px" src="https://wpimg.wallstcn.com/9c0b719b-5551-4c1e-b776-63994632d94a.png" /></a><p>Admin Dashboard Templates made with Vue, React and Angular.</p>
|
<a href="https://flatlogic.com/admin-dashboards?from=vue-element-admin"><img width="150px" src="https://wpimg.wallstcn.com/9c0b719b-5551-4c1e-b776-63994632d94a.png" /></a><p>Admin Dashboard Templates made with Vue, React and Angular.</p>
|
||||||
@@ -91,7 +94,6 @@ Become a sponsor and get your logo on our README on GitHub with a link to your s
|
|||||||
- 权限验证
|
- 权限验证
|
||||||
- 页面权限
|
- 页面权限
|
||||||
- 指令权限
|
- 指令权限
|
||||||
- 权限配置
|
|
||||||
- 二步登录
|
- 二步登录
|
||||||
|
|
||||||
- 多环境发布
|
- 多环境发布
|
||||||
@@ -104,7 +106,7 @@ Become a sponsor and get your logo on our README on GitHub with a link to your s
|
|||||||
- 动态面包屑
|
- 动态面包屑
|
||||||
- 快捷导航(标签页)
|
- 快捷导航(标签页)
|
||||||
- Svg Sprite 图标
|
- Svg Sprite 图标
|
||||||
- 本地/后端 mock 数据
|
- 本地mock数据
|
||||||
- Screenfull全屏
|
- Screenfull全屏
|
||||||
- 自适应收缩侧边栏
|
- 自适应收缩侧边栏
|
||||||
|
|
||||||
@@ -115,13 +117,14 @@ Become a sponsor and get your logo on our README on GitHub with a link to your s
|
|||||||
|
|
||||||
- Excel
|
- Excel
|
||||||
- 导出excel
|
- 导出excel
|
||||||
|
- 导出zip
|
||||||
- 导入excel
|
- 导入excel
|
||||||
- 前端可视化excel
|
- 前端可视化excel
|
||||||
- 导出zip
|
|
||||||
|
|
||||||
- 表格
|
- 表格
|
||||||
- 动态表格
|
- 动态表格
|
||||||
- 拖拽表格
|
- 拖拽表格
|
||||||
|
- 树形表格
|
||||||
- 内联编辑
|
- 内联编辑
|
||||||
|
|
||||||
- 错误页面
|
- 错误页面
|
||||||
@@ -155,9 +158,6 @@ Become a sponsor and get your logo on our README on GitHub with a link to your s
|
|||||||
# 克隆项目
|
# 克隆项目
|
||||||
git clone https://github.com/PanJiaChen/vue-element-admin.git
|
git clone https://github.com/PanJiaChen/vue-element-admin.git
|
||||||
|
|
||||||
# 进入项目目录
|
|
||||||
cd vue-element-admin
|
|
||||||
|
|
||||||
# 安装依赖
|
# 安装依赖
|
||||||
npm install
|
npm install
|
||||||
|
|
||||||
@@ -174,7 +174,7 @@ npm run dev
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 构建测试环境
|
# 构建测试环境
|
||||||
npm run build:stage
|
npm run build:sit
|
||||||
|
|
||||||
# 构建生产环境
|
# 构建生产环境
|
||||||
npm run build:prod
|
npm run build:prod
|
||||||
@@ -183,16 +183,19 @@ npm run build:prod
|
|||||||
## 其它
|
## 其它
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 预览发布环境效果
|
# --report to build with bundle size analytics
|
||||||
npm run preview
|
npm run build:prod
|
||||||
|
|
||||||
# 预览发布环境效果 + 静态资源分析
|
# --generate a bundle size analytics. default: bundle-report.html
|
||||||
npm run preview -- --report
|
npm run build:prod --generate_report
|
||||||
|
|
||||||
# 代码格式检查
|
# --preview to start a server in local to preview
|
||||||
|
npm run build:prod --preview
|
||||||
|
|
||||||
|
# lint code
|
||||||
npm run lint
|
npm run lint
|
||||||
|
|
||||||
# 代码格式检查并自动修复
|
# auto fix
|
||||||
npm run lint -- --fix
|
npm run lint -- --fix
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -215,8 +218,6 @@ Detailed changes for each release are documented in the [release notes](https://
|
|||||||
|
|
||||||
[Paypal Me](https://www.paypal.me/panfree23)
|
[Paypal Me](https://www.paypal.me/panfree23)
|
||||||
|
|
||||||
[Buy me a coffee](https://www.buymeacoffee.com/Pan)
|
|
||||||
|
|
||||||
## Browsers support
|
## Browsers support
|
||||||
|
|
||||||
Modern browsers and Internet Explorer 10+.
|
Modern browsers and Internet Explorer 10+.
|
||||||
|
@@ -5,9 +5,7 @@ const rawArgv = process.argv.slice(2)
|
|||||||
const args = rawArgv.join(' ')
|
const args = rawArgv.join(' ')
|
||||||
|
|
||||||
if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
|
if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
|
||||||
const report = rawArgv.includes('--report')
|
run(`vue-cli-service build ${args} --report`)
|
||||||
|
|
||||||
run(`vue-cli-service build ${args}`)
|
|
||||||
|
|
||||||
const port = 9526
|
const port = 9526
|
||||||
const publicPath = config.publicPath
|
const publicPath = config.publicPath
|
||||||
@@ -23,12 +21,13 @@ if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
app.listen(port, function () {
|
app.listen(port, function() {
|
||||||
console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`))
|
console.log(
|
||||||
if (report) {
|
chalk.green(`> Preview at http://localhost:${port}${publicPath}`)
|
||||||
console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}/report.html`))
|
)
|
||||||
}
|
console.log(
|
||||||
|
chalk.green(`> Report at http://localhost:${port}${publicPath}/report.html`)
|
||||||
|
)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
run(`vue-cli-service build ${args}`)
|
run(`vue-cli-service build ${args}`)
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
verbose: true,
|
verbose: true,
|
||||||
moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
|
moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
|
||||||
transformIgnorePatterns: [
|
// transformIgnorePatterns: [
|
||||||
'node_modules/(?!(babel-jest|jest-vue-preprocessor)/)'
|
// 'node_modules/(?!(babel-jest|jest-vue-preprocessor)/)'
|
||||||
],
|
// ],
|
||||||
transform: {
|
transform: {
|
||||||
'^.+\\.vue$': 'vue-jest',
|
'^.+\\.vue$': 'vue-jest',
|
||||||
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
|
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
|
||||||
|
@@ -11,10 +11,6 @@ export function mockXHR() {
|
|||||||
Mock.XHR.prototype.send = function() {
|
Mock.XHR.prototype.send = function() {
|
||||||
if (this.custom.xhr) {
|
if (this.custom.xhr) {
|
||||||
this.custom.xhr.withCredentials = this.withCredentials || false
|
this.custom.xhr.withCredentials = this.withCredentials || false
|
||||||
|
|
||||||
if (this.responseType) {
|
|
||||||
this.custom.xhr.responseType = this.responseType
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.proxy_send(...arguments)
|
this.proxy_send(...arguments)
|
||||||
}
|
}
|
||||||
|
24
mock/user.js
24
mock/user.js
@@ -30,19 +30,9 @@ export default [
|
|||||||
type: 'post',
|
type: 'post',
|
||||||
response: config => {
|
response: config => {
|
||||||
const { username } = config.body
|
const { username } = config.body
|
||||||
const token = tokens[username]
|
|
||||||
|
|
||||||
// mock error
|
|
||||||
if (!token) {
|
|
||||||
return {
|
|
||||||
code: 60204,
|
|
||||||
message: 'Account and password are incorrect.'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
code: 20000,
|
code: 20000,
|
||||||
data: token
|
data: tokens[username]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -53,19 +43,9 @@ export default [
|
|||||||
type: 'get',
|
type: 'get',
|
||||||
response: config => {
|
response: config => {
|
||||||
const { token } = config.query
|
const { token } = config.query
|
||||||
const info = users[token]
|
|
||||||
|
|
||||||
// mock error
|
|
||||||
if (!info) {
|
|
||||||
return {
|
|
||||||
code: 50008,
|
|
||||||
message: 'Login failed, unable to get user details.'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
code: 20000,
|
code: 20000,
|
||||||
data: info
|
data: users[token]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
24
package.json
24
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "vue-element-admin",
|
"name": "vue-element-admin",
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"description": "A magical vue admin. An out-of-box UI solution for enterprise applications. Newest development stack of vue. Lots of awesome features",
|
"description": "A magical vue admin. Typical templates for enterprise applications. Newest development stack of vue. Lots of awesome features",
|
||||||
"author": "Pan <panfree23@gmail.com>",
|
"author": "Pan <panfree23@gmail.com>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -10,8 +10,8 @@
|
|||||||
"build:stage": "vue-cli-service build --mode staging",
|
"build:stage": "vue-cli-service build --mode staging",
|
||||||
"preview": "node build/index.js --preview",
|
"preview": "node build/index.js --preview",
|
||||||
"lint": "eslint --ext .js,.vue src",
|
"lint": "eslint --ext .js,.vue src",
|
||||||
|
"test": "npm run lint",
|
||||||
"test:unit": "vue-cli-service test:unit",
|
"test:unit": "vue-cli-service test:unit",
|
||||||
"test:ci": "npm run lint && npm run test:unit",
|
|
||||||
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
|
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
|
||||||
"new": "plop"
|
"new": "plop"
|
||||||
},
|
},
|
||||||
@@ -28,12 +28,10 @@
|
|||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"vue",
|
"vue",
|
||||||
"admin",
|
|
||||||
"dashboard",
|
|
||||||
"element-ui",
|
"element-ui",
|
||||||
"boilerplate",
|
"admin",
|
||||||
"admin-template",
|
"management-system",
|
||||||
"management-system"
|
"admin-template"
|
||||||
],
|
],
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -44,12 +42,12 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "0.18.0",
|
"axios": "0.18.0",
|
||||||
"clipboard": "2.0.4",
|
"clipboard": "1.7.1",
|
||||||
"codemirror": "5.45.0",
|
"codemirror": "5.45.0",
|
||||||
"driver.js": "0.9.5",
|
"driver.js": "0.9.5",
|
||||||
"dropzone": "5.5.1",
|
"dropzone": "5.5.1",
|
||||||
"echarts": "4.2.1",
|
"echarts": "4.2.1",
|
||||||
"element-ui": "2.7.0",
|
"element-ui": "2.6.3",
|
||||||
"file-saver": "2.0.1",
|
"file-saver": "2.0.1",
|
||||||
"fuse.js": "3.4.4",
|
"fuse.js": "3.4.4",
|
||||||
"js-cookie": "2.2.0",
|
"js-cookie": "2.2.0",
|
||||||
@@ -58,7 +56,7 @@
|
|||||||
"normalize.css": "7.0.0",
|
"normalize.css": "7.0.0",
|
||||||
"nprogress": "0.2.0",
|
"nprogress": "0.2.0",
|
||||||
"path-to-regexp": "2.4.0",
|
"path-to-regexp": "2.4.0",
|
||||||
"screenfull": "4.2.0",
|
"screenfull": "4.1.0",
|
||||||
"showdown": "1.9.0",
|
"showdown": "1.9.0",
|
||||||
"sortablejs": "1.8.4",
|
"sortablejs": "1.8.4",
|
||||||
"tui-editor": "1.3.3",
|
"tui-editor": "1.3.3",
|
||||||
@@ -74,9 +72,9 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "7.0.0",
|
"@babel/core": "7.0.0",
|
||||||
"@babel/register": "7.0.0",
|
"@babel/register": "7.0.0",
|
||||||
"@vue/cli-plugin-babel": "3.5.3",
|
"@vue/cli-plugin-babel": "3.5.1",
|
||||||
"@vue/cli-plugin-unit-jest": "3.5.3",
|
"@vue/cli-plugin-unit-jest": "3.5.1",
|
||||||
"@vue/cli-service": "3.5.3",
|
"@vue/cli-service": "3.5.1",
|
||||||
"@vue/test-utils": "1.0.0-beta.29",
|
"@vue/test-utils": "1.0.0-beta.29",
|
||||||
"babel-core": "7.0.0-bridge.0",
|
"babel-core": "7.0.0-bridge.0",
|
||||||
"babel-eslint": "10.0.1",
|
"babel-eslint": "10.0.1",
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
|
||||||
export function searchUser(name) {
|
export function userSearch(name) {
|
||||||
return request({
|
return request({
|
||||||
url: '/search/user',
|
url: '/search/user',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
|
@@ -88,29 +88,29 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.back-to-ceiling {
|
.back-to-ceiling {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.back-to-ceiling:hover {
|
.back-to-ceiling:hover {
|
||||||
background: #d5dbe7;
|
background: #d5dbe7;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fade-enter-active,
|
.fade-enter-active,
|
||||||
.fade-leave-active {
|
.fade-leave-active {
|
||||||
transition: opacity .5s;
|
transition: opacity .5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fade-enter,
|
.fade-enter,
|
||||||
.fade-leave-to {
|
.fade-leave-to {
|
||||||
opacity: 0
|
opacity: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
.back-to-ceiling .Icon {
|
.back-to-ceiling .Icon {
|
||||||
fill: #9aaabf;
|
fill: #9aaabf;
|
||||||
background: none;
|
background: none;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@@ -59,15 +59,14 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.app-breadcrumb.el-breadcrumb {
|
.app-breadcrumb.el-breadcrumb {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
|
.no-redirect {
|
||||||
.no-redirect {
|
color: #97a8be;
|
||||||
color: #97a8be;
|
cursor: text;
|
||||||
cursor: text;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@@ -237,7 +237,7 @@ export default {
|
|||||||
|
|
||||||
.dropzone .dz-preview:hover .dz-image img {
|
.dropzone .dz-preview:hover .dz-image img {
|
||||||
transform: none;
|
transform: none;
|
||||||
filter: none;
|
-webkit-filter: none;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
@@ -2,9 +2,7 @@
|
|||||||
<div ref="rightPanel" :class="{show:show}" class="rightPanel-container">
|
<div ref="rightPanel" :class="{show:show}" class="rightPanel-container">
|
||||||
<div class="rightPanel-background" />
|
<div class="rightPanel-background" />
|
||||||
<div class="rightPanel">
|
<div class="rightPanel">
|
||||||
<div class="handle-button" :style="{'top':buttonTop+'px','background-color':theme}" @click="show=!show">
|
<el-button class="handle-button" :style="{'top':buttonTop+'px'}" type="primary" circle :icon="show?'el-icon-close':'el-icon-setting'" @click="show=!show" />
|
||||||
<i :class="show?'el-icon-close':'el-icon-setting'" />
|
|
||||||
</div>
|
|
||||||
<div class="rightPanel-items">
|
<div class="rightPanel-items">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
@@ -32,11 +30,6 @@ export default {
|
|||||||
show: false
|
show: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
theme() {
|
|
||||||
return this.$store.state.settings.theme
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
watch: {
|
||||||
show(value) {
|
show(value) {
|
||||||
if (value && !this.clickNotClose) {
|
if (value && !this.clickNotClose) {
|
||||||
@@ -137,16 +130,7 @@ export default {
|
|||||||
height: 48px;
|
height: 48px;
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
cursor: pointer;
|
|
||||||
pointer-events: auto;
|
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #fff;
|
|
||||||
line-height: 48px;
|
|
||||||
|
|
||||||
i {
|
|
||||||
font-size: 24px;
|
|
||||||
line-height: 48px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@@ -17,9 +17,6 @@ export default {
|
|||||||
mounted() {
|
mounted() {
|
||||||
this.init()
|
this.init()
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
|
||||||
this.destroy()
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
click() {
|
click() {
|
||||||
if (!screenfull.enabled) {
|
if (!screenfull.enabled) {
|
||||||
@@ -31,17 +28,11 @@ export default {
|
|||||||
}
|
}
|
||||||
screenfull.toggle()
|
screenfull.toggle()
|
||||||
},
|
},
|
||||||
change() {
|
|
||||||
this.isFullscreen = screenfull.isFullscreen
|
|
||||||
},
|
|
||||||
init() {
|
init() {
|
||||||
if (screenfull.enabled) {
|
if (screenfull.enabled) {
|
||||||
screenfull.on('change', this.change)
|
screenfull.on('change', () => {
|
||||||
}
|
this.isFullscreen = screenfull.isFullscreen
|
||||||
},
|
})
|
||||||
destroy() {
|
|
||||||
if (screenfull.enabled) {
|
|
||||||
screenfull.off('change', this.change)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-color-picker
|
<el-color-picker
|
||||||
v-model="theme"
|
v-model="theme"
|
||||||
:predefine="['#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]"
|
:predefine="['#409EFF', '#11a983', '#13c2c2', '#6959CD', '#f5222d', '#eb2f96', '#DB7093', '#e6a23c', '#8B8989', '#212121']"
|
||||||
class="theme-picker"
|
class="theme-picker"
|
||||||
popper-class="theme-picker-dropdown"
|
popper-class="theme-picker-dropdown"
|
||||||
/>
|
/>
|
||||||
@@ -11,18 +11,17 @@
|
|||||||
|
|
||||||
const version = require('element-ui/package.json').version // element-ui version from node_modules
|
const version = require('element-ui/package.json').version // element-ui version from node_modules
|
||||||
const ORIGINAL_THEME = '#409EFF' // default color
|
const ORIGINAL_THEME = '#409EFF' // default color
|
||||||
import defaultSettings from '@/settings'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
chalk: '', // content of theme-chalk css
|
chalk: '', // content of theme-chalk css
|
||||||
theme: defaultSettings.theme
|
theme: ORIGINAL_THEME
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
async theme(val) {
|
async theme(val) {
|
||||||
const oldVal = this.chalk ? this.theme : ORIGINAL_THEME
|
const oldVal = this.theme
|
||||||
if (typeof val !== 'string') return
|
if (typeof val !== 'string') return
|
||||||
const themeCluster = this.getThemeCluster(val.replace('#', ''))
|
const themeCluster = this.getThemeCluster(val.replace('#', ''))
|
||||||
const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
|
const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
|
||||||
@@ -71,8 +70,6 @@ export default {
|
|||||||
style.innerText = this.updateStyle(innerText, originalCluster, themeCluster)
|
style.innerText = this.updateStyle(innerText, originalCluster, themeCluster)
|
||||||
})
|
})
|
||||||
|
|
||||||
this.$emit('change', val)
|
|
||||||
|
|
||||||
$message.close()
|
$message.close()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
220
src/components/TreeTable/README.md
Normal file
220
src/components/TreeTable/README.md
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
|
||||||
|
- [Enlgish](#Brief)
|
||||||
|
|
||||||
|
# 中文
|
||||||
|
|
||||||
|
## 写在前面
|
||||||
|
|
||||||
|
此组件仅提供一个创建 `TreeTable` 的解决思路。它基于`element-ui`的 table 组件实现,通过`el-table`的`row-style`方法,在里面判断元素是否需要隐藏或者显示,从而实现`TreeTable`的展开与收起。
|
||||||
|
|
||||||
|
并且本组件充分利用 `vue` 插槽的特性来方便用户自定义。
|
||||||
|
|
||||||
|
`evel.js` 里面,`addAttrs` 方法会给数据添加几个属性,`treeTotable` 会对数组扁平化。这些操作都不会破坏源数据,只是会新增属性。
|
||||||
|
|
||||||
|
## Props 说明
|
||||||
|
|
||||||
|
| Attribute | Description | Type | Default |
|
||||||
|
| :--------------: | :--------------------------------- | :-----: | :------: |
|
||||||
|
| data | 原始展示数据 | Array | [] |
|
||||||
|
| columns | 列属性 | Array | [] |
|
||||||
|
| defaultExpandAll | 默认是否全部展开 | Boolean | false |
|
||||||
|
| defaultChildren | 指定子树为节点对象的某个属性值 | String | children | |
|
||||||
|
| indent | 相邻级节点间的水平缩进,单位为像素 | Number | 50 |
|
||||||
|
|
||||||
|
> 任何 `el-table` 的属性都支持,例如`border`、`fit`、`size`或者`@select`、`@cell-click`等方法。详情属性见`el-table`文档。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 代码示例
|
||||||
|
|
||||||
|
```html
|
||||||
|
<tree-table :data="data" :columns="columns" border>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### data(**必填**)
|
||||||
|
|
||||||
|
```js
|
||||||
|
const data = [
|
||||||
|
{
|
||||||
|
name:'1'
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: '1-1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '1-2'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: `2`
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### columns(**必填**)
|
||||||
|
|
||||||
|
- label: 显示在表头的文字
|
||||||
|
- key: 对应 data 的 key。treeTable 将显示相应的 value
|
||||||
|
- expand: `true` or `false`。若为 true,则在该列显示展开收起图标
|
||||||
|
- checkbox: `true` or `false`。若为 true,则在该列显示`checkbox`
|
||||||
|
- width: 每列的宽度,为一个数字(可选)。例如`200`
|
||||||
|
- align: 对齐方式 `left/center/right`
|
||||||
|
- header-align: 表头对齐方式 `left/center/right`
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
label: 'Checkbox',
|
||||||
|
checkbox: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
key: 'id',
|
||||||
|
expand: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Event',
|
||||||
|
key: 'event',
|
||||||
|
width: 200,
|
||||||
|
align: 'left'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Scope',
|
||||||
|
key: 'scope'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
> 树表组件将会根据 columns 的 key 属性生成具名插槽,如果你需要对列数据进行自定义,通过插槽即可实现
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template slot="your key" slot-scope="{scope}">
|
||||||
|
<el-tag>level: {{ scope.row._level }}</el-tag>
|
||||||
|
<el-tag>expand: {{ scope.row._expand }}</el-tag>
|
||||||
|
<el-tag>select: {{ scope.row._select }}</el-tag>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Events
|
||||||
|
|
||||||
|
目前提供了几个方法,不过只是`beta`版本,之后很可能会修改。
|
||||||
|
|
||||||
|
```js
|
||||||
|
this.$refs.TreeTable.addChild(row, data) //添加子元素
|
||||||
|
this.$refs.TreeTable.addBrother(row, data) //添加兄弟元素
|
||||||
|
this.$refs.TreeTable.delete(row) //删除该元素
|
||||||
|
```
|
||||||
|
|
||||||
|
## 其他
|
||||||
|
|
||||||
|
如果有其他的需求,请参考[el-table](http://element-cn.eleme.io/#/en-US/component/table)的 api 自行修改 index.vue
|
||||||
|
|
||||||
|
# English
|
||||||
|
|
||||||
|
## Brief
|
||||||
|
|
||||||
|
This component only provides a solution for creating `TreeTable`. It is based on the `element-ui` table component. It uses the `row-style` method of `el-table` to determine whether the element needs to be hidden or displayed.
|
||||||
|
|
||||||
|
And this component makes full use of the features of the `vue` slot to make it user-friendly.
|
||||||
|
|
||||||
|
In `evel.js`, the `addAttrs` method adds several properties to the data, and `treeTotable` flattens the array. None of these operations will destroy the source data, just add properties.
|
||||||
|
|
||||||
|
## Props
|
||||||
|
|
||||||
|
| Attribute | Description | Type | Default |
|
||||||
|
| :--------------: | :----------------------------------------------------------- | :-----: | :------: |
|
||||||
|
| data | original display data | Array | [] |
|
||||||
|
| columns | column attribute | Array | [] |
|
||||||
|
| defaultExpandAll | whether to expand all nodes by default | Boolean | false |
|
||||||
|
| defaultChildren | specify which node object is used as the node's subtree | String | children | |
|
||||||
|
| indent | horizontal indentation of nodes in adjacent levels in pixels | Number | 50 |
|
||||||
|
|
||||||
|
> Any of the `el-table` properties are supported, such as `border`, `fit`, `size` or `@select`, `@cell-click`. See the ʻel-table` documentation for details.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```html
|
||||||
|
<tree-table :data="data" :columns="columns" border>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### data(**Required**)
|
||||||
|
|
||||||
|
```js
|
||||||
|
const data = [
|
||||||
|
{
|
||||||
|
name:'1'
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: '1-1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '1-2'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: `2`
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### columns(**Required**)
|
||||||
|
|
||||||
|
- label: text displayed in the header
|
||||||
|
- key: data.key will show in column
|
||||||
|
- expand: `true` or `false`
|
||||||
|
- checkbox: `true` or `false`
|
||||||
|
- width: column width 。such as `200`
|
||||||
|
- align: alignment `left/center/right`
|
||||||
|
- header-align: alignment of the table header `left/center/right`
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
label: 'Checkbox',
|
||||||
|
checkbox: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
key: 'id',
|
||||||
|
expand: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Event',
|
||||||
|
key: 'event',
|
||||||
|
width: 200,
|
||||||
|
align: 'left'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Scope',
|
||||||
|
key: 'scope'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
> The tree table component will generate a named slot based on the key property of columns. If you need to customize the column data, you can do it through the slot.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template slot="your key" slot-scope="{scope}">
|
||||||
|
<el-tag>level: {{ scope.row._level }}</el-tag>
|
||||||
|
<el-tag>expand: {{ scope.row._expand }}</el-tag>
|
||||||
|
<el-tag>select: {{ scope.row._select }}</el-tag>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Events
|
||||||
|
|
||||||
|
Several methods are currently available, but only the `beta` version, which is likely to be modified later.
|
||||||
|
|
||||||
|
```js
|
||||||
|
this.$refs.TreeTable.addChild(row, data) //Add child elements
|
||||||
|
this.$refs.TreeTable.addBrother(row, data) //Add a sibling element
|
||||||
|
this.$refs.TreeTable.delete(row) //Delete the element
|
||||||
|
```
|
||||||
|
|
||||||
|
## Other
|
||||||
|
|
||||||
|
If you have other requirements, please refer to the [el-table](http://element-cn.eleme.io/#/en-US/component/table) api to modify the index.vue
|
48
src/components/TreeTable/eval.js
Normal file
48
src/components/TreeTable/eval.js
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
|
||||||
|
// Flattened array
|
||||||
|
export default function treeToArray(data, children = 'children') {
|
||||||
|
let tmp = []
|
||||||
|
data.forEach((item, index) => {
|
||||||
|
Vue.set(item, '_index', index)
|
||||||
|
tmp.push(item)
|
||||||
|
if (item[children] && item[children].length > 0) {
|
||||||
|
const res = treeToArray(item[children], children)
|
||||||
|
tmp = tmp.concat(res)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return tmp
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addAttrs(data, { parent = null, preIndex = false, level = 0, expand = false, children = 'children', show = true, select = false } = {}) {
|
||||||
|
data.forEach((item, index) => {
|
||||||
|
const _id = (preIndex ? `${preIndex}-${index}` : index) + ''
|
||||||
|
Vue.set(item, '_id', _id)
|
||||||
|
Vue.set(item, '_level', level)
|
||||||
|
Vue.set(item, '_expand', expand)
|
||||||
|
Vue.set(item, '_parent', parent)
|
||||||
|
Vue.set(item, '_show', show)
|
||||||
|
Vue.set(item, '_select', select)
|
||||||
|
if (item[children] && item[children].length > 0) {
|
||||||
|
addAttrs(item[children], {
|
||||||
|
parent: item,
|
||||||
|
level: level + 1,
|
||||||
|
expand,
|
||||||
|
preIndex: _id,
|
||||||
|
children,
|
||||||
|
status,
|
||||||
|
select
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function cleanParentAttr(data, children = 'children') {
|
||||||
|
data.forEach(item => {
|
||||||
|
item._parent = null
|
||||||
|
if (item[children] && item[children].length > 0) {
|
||||||
|
addAttrs(item[children], children)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return data
|
||||||
|
}
|
193
src/components/TreeTable/index.vue
Normal file
193
src/components/TreeTable/index.vue
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
<template>
|
||||||
|
<el-table :data="tableData" :row-style="showRow" v-bind="$attrs" v-on="$listeners">
|
||||||
|
<slot name="selection" />
|
||||||
|
<slot name="pre-column" />
|
||||||
|
<el-table-column
|
||||||
|
v-for="item in columns"
|
||||||
|
:key="item.key"
|
||||||
|
:label="item.label"
|
||||||
|
:width="item.width"
|
||||||
|
:align="item.align||'center'"
|
||||||
|
:header-align="item.headerAlign"
|
||||||
|
>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<slot :scope="scope" :name="item.key">
|
||||||
|
<template v-if="item.expand">
|
||||||
|
<span :style="{'padding-left':+scope.row._level*indent + 'px'} " />
|
||||||
|
<span v-show="showSperadIcon(scope.row)" class="tree-ctrl" @click="toggleExpanded(scope.$index)">
|
||||||
|
<i v-if="!scope.row._expand" class="el-icon-plus" />
|
||||||
|
<i v-else class="el-icon-minus" />
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template v-if="item.checkbox">
|
||||||
|
<el-checkbox
|
||||||
|
v-if="scope.row[defaultChildren]&&scope.row[defaultChildren].length>0"
|
||||||
|
v-model="scope.row._select"
|
||||||
|
:style="{'padding-left':+scope.row._level*indent + 'px'} "
|
||||||
|
:indeterminate="scope.row._select"
|
||||||
|
@change="handleCheckAllChange(scope.row)"
|
||||||
|
/>
|
||||||
|
<el-checkbox
|
||||||
|
v-else
|
||||||
|
v-model="scope.row._select"
|
||||||
|
:style="{'padding-left':+scope.row._level*indent + 'px'} "
|
||||||
|
@change="handleCheckAllChange(scope.row)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
{{ scope.row[item.key] }}
|
||||||
|
</slot>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import treeToArray, { addAttrs } from './eval.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'TreeTable',
|
||||||
|
props: {
|
||||||
|
data: {
|
||||||
|
type: Array,
|
||||||
|
required: true,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
defaultExpandAll: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
defaultChildren: {
|
||||||
|
type: String,
|
||||||
|
default: 'children'
|
||||||
|
},
|
||||||
|
indent: {
|
||||||
|
type: Number,
|
||||||
|
default: 50
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
guard: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
children() {
|
||||||
|
return this.defaultChildren
|
||||||
|
},
|
||||||
|
tableData() {
|
||||||
|
const data = this.data
|
||||||
|
if (this.data.length === 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
addAttrs(data, {
|
||||||
|
expand: this.defaultExpandAll,
|
||||||
|
children: this.defaultChildren
|
||||||
|
})
|
||||||
|
|
||||||
|
const retval = treeToArray(data, this.defaultChildren)
|
||||||
|
return retval
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
addBrother(row, data) {
|
||||||
|
if (row._parent) {
|
||||||
|
row._parent.children.push(data)
|
||||||
|
} else {
|
||||||
|
this.data.push(data)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
addChild(row, data) {
|
||||||
|
if (!row.children) {
|
||||||
|
this.$set(row, 'children', [])
|
||||||
|
}
|
||||||
|
row.children.push(data)
|
||||||
|
},
|
||||||
|
delete(row) {
|
||||||
|
const { _index, _parent } = row
|
||||||
|
if (_parent) {
|
||||||
|
_parent.children.splice(_index, 1)
|
||||||
|
} else {
|
||||||
|
this.data.splice(_index, 1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getData() {
|
||||||
|
return this.tableData
|
||||||
|
},
|
||||||
|
showRow: function({ row }) {
|
||||||
|
const parent = row._parent
|
||||||
|
const show = parent ? parent._expand && parent._show : true
|
||||||
|
row._show = show
|
||||||
|
return show
|
||||||
|
? 'animation:treeTableShow 1s;-webkit-animation:treeTableShow 1s;'
|
||||||
|
: 'display:none;'
|
||||||
|
},
|
||||||
|
showSperadIcon(record) {
|
||||||
|
return record[this.children] && record[this.children].length > 0
|
||||||
|
},
|
||||||
|
toggleExpanded(trIndex) {
|
||||||
|
const record = this.tableData[trIndex]
|
||||||
|
const expand = !record._expand
|
||||||
|
record._expand = expand
|
||||||
|
},
|
||||||
|
handleCheckAllChange(row) {
|
||||||
|
this.selcetRecursion(row, row._select, this.defaultChildren)
|
||||||
|
this.isIndeterminate = row._select
|
||||||
|
},
|
||||||
|
selcetRecursion(row, select, children = 'children') {
|
||||||
|
if (select) {
|
||||||
|
this.$set(row, '_expand', true)
|
||||||
|
this.$set(row, '_show', true)
|
||||||
|
}
|
||||||
|
const sub_item = row[children]
|
||||||
|
if (sub_item && sub_item.length > 0) {
|
||||||
|
sub_item.map(child => {
|
||||||
|
child._select = select
|
||||||
|
this.selcetRecursion(child, select, children)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateTreeNode(item) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
const { _id, _parent } = item
|
||||||
|
const index = _id.split('-').slice(-1)[0] // get last index
|
||||||
|
if (_parent) {
|
||||||
|
_parent.children.splice(index, 1, item)
|
||||||
|
resolve(this.data)
|
||||||
|
} else {
|
||||||
|
this.data.splice(index, 1, item)
|
||||||
|
resolve(this.data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@keyframes treeTableShow {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@-webkit-keyframes treeTableShow {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-ctrl {
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #2196f3;
|
||||||
|
}
|
||||||
|
</style>
|
@@ -43,6 +43,8 @@ export default {
|
|||||||
dragTable: 'Drag Table',
|
dragTable: 'Drag Table',
|
||||||
inlineEditTable: 'Inline Edit',
|
inlineEditTable: 'Inline Edit',
|
||||||
complexTable: 'Complex Table',
|
complexTable: 'Complex Table',
|
||||||
|
treeTable: 'Tree Table',
|
||||||
|
customTreeTable: 'Custom TreeTable',
|
||||||
tab: 'Tab',
|
tab: 'Tab',
|
||||||
form: 'Form',
|
form: 'Form',
|
||||||
createArticle: 'Create Article',
|
createArticle: 'Create Article',
|
||||||
|
@@ -43,6 +43,8 @@ export default {
|
|||||||
dragTable: 'Arrastrar tabla',
|
dragTable: 'Arrastrar tabla',
|
||||||
inlineEditTable: 'Editor',
|
inlineEditTable: 'Editor',
|
||||||
complexTable: 'Complex Table',
|
complexTable: 'Complex Table',
|
||||||
|
treeTable: 'Tree Table',
|
||||||
|
customTreeTable: 'Custom TreeTable',
|
||||||
tab: 'Pestaña',
|
tab: 'Pestaña',
|
||||||
form: 'Formulario',
|
form: 'Formulario',
|
||||||
createArticle: 'Crear artículo',
|
createArticle: 'Crear artículo',
|
||||||
|
@@ -43,6 +43,8 @@ export default {
|
|||||||
dragTable: '拖拽Table',
|
dragTable: '拖拽Table',
|
||||||
inlineEditTable: 'Table内编辑',
|
inlineEditTable: 'Table内编辑',
|
||||||
complexTable: '综合Table',
|
complexTable: '综合Table',
|
||||||
|
treeTable: '树形表格',
|
||||||
|
customTreeTable: '自定义树表',
|
||||||
tab: 'Tab',
|
tab: 'Tab',
|
||||||
form: '表单',
|
form: '表单',
|
||||||
createArticle: '创建文章',
|
createArticle: '创建文章',
|
||||||
|
@@ -86,6 +86,12 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.hasTagsView {
|
||||||
|
.navbar {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.navbar {
|
.navbar {
|
||||||
height: 50px;
|
height: 50px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
<div class="drawer-item">
|
<div class="drawer-item">
|
||||||
<span>{{ $t('settings.theme') }}</span>
|
<span>{{ $t('settings.theme') }}</span>
|
||||||
<theme-picker style="float: right;height: 26px;margin: -3px 8px 0 0;" @change="themeChange" />
|
<theme-picker style="float: right;height: 26px;margin: -3px 8px 0 0;" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="drawer-item">
|
<div class="drawer-item">
|
||||||
@@ -69,14 +69,6 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
themeChange(val) {
|
|
||||||
this.$store.dispatch('settings/changeSetting', {
|
|
||||||
key: 'theme',
|
|
||||||
value: val
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="!item.hidden" class="menu-wrapper">
|
<div v-if="!item.hidden" class="menu-wrapper">
|
||||||
<template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
|
<template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
|
||||||
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
|
<app-link :to="resolvePath(onlyOneChild.path)">
|
||||||
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
|
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
|
||||||
<item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="generateTitle(onlyOneChild.meta.title)" />
|
<item v-if="onlyOneChild.meta" :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="generateTitle(onlyOneChild.meta.title)" />
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
</app-link>
|
</app-link>
|
||||||
</template>
|
</template>
|
||||||
|
@@ -14,9 +14,6 @@ export default {
|
|||||||
beforeMount() {
|
beforeMount() {
|
||||||
window.addEventListener('resize', this.resizeHandler)
|
window.addEventListener('resize', this.resizeHandler)
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
|
||||||
window.removeEventListener('resize', this.resizeHandler)
|
|
||||||
},
|
|
||||||
mounted() {
|
mounted() {
|
||||||
const isMobile = this.isMobile()
|
const isMobile = this.isMobile()
|
||||||
if (isMobile) {
|
if (isMobile) {
|
||||||
|
@@ -4,12 +4,13 @@ import Router from 'vue-router'
|
|||||||
Vue.use(Router)
|
Vue.use(Router)
|
||||||
|
|
||||||
/* Layout */
|
/* Layout */
|
||||||
import Layout from '@/layout'
|
import Layout from '@/layout/Layout'
|
||||||
|
|
||||||
/* Router Modules */
|
/* Router Modules */
|
||||||
import componentsRouter from './modules/components'
|
import componentsRouter from './modules/components'
|
||||||
import chartsRouter from './modules/charts'
|
import chartsRouter from './modules/charts'
|
||||||
import tableRouter from './modules/table'
|
import tableRouter from './modules/table'
|
||||||
|
import treeTableRouter from './modules/tree-table'
|
||||||
import nestedRouter from './modules/nested'
|
import nestedRouter from './modules/nested'
|
||||||
|
|
||||||
/** note: sub-menu only appear when children.length>=1
|
/** note: sub-menu only appear when children.length>=1
|
||||||
@@ -174,6 +175,7 @@ export const asyncRoutes = [
|
|||||||
chartsRouter,
|
chartsRouter,
|
||||||
nestedRouter,
|
nestedRouter,
|
||||||
tableRouter,
|
tableRouter,
|
||||||
|
treeTableRouter,
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/example',
|
path: '/example',
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/** When your routing table is too long, you can split it into small modules**/
|
/** When your routing table is too long, you can split it into small modules**/
|
||||||
|
|
||||||
import Layout from '@/layout'
|
import Layout from '@/layout/Layout'
|
||||||
|
|
||||||
const chartsRouter = {
|
const chartsRouter = {
|
||||||
path: '/charts',
|
path: '/charts',
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/** When your routing table is too long, you can split it into small modules**/
|
/** When your routing table is too long, you can split it into small modules**/
|
||||||
|
|
||||||
import Layout from '@/layout'
|
import Layout from '@/layout/Layout'
|
||||||
|
|
||||||
const componentsRouter = {
|
const componentsRouter = {
|
||||||
path: '/components',
|
path: '/components',
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/** When your routing table is too long, you can split it into small modules**/
|
/** When your routing table is too long, you can split it into small modules**/
|
||||||
|
|
||||||
import Layout from '@/layout'
|
import Layout from '@/layout/Layout'
|
||||||
|
|
||||||
const nestedRouter = {
|
const nestedRouter = {
|
||||||
path: '/nested',
|
path: '/nested',
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/** When your routing table is too long, you can split it into small modules**/
|
/** When your routing table is too long, you can split it into small modules**/
|
||||||
|
|
||||||
import Layout from '@/layout'
|
import Layout from '@/layout/Layout'
|
||||||
|
|
||||||
const tableRouter = {
|
const tableRouter = {
|
||||||
path: '/table',
|
path: '/table',
|
||||||
|
29
src/router/modules/tree-table.js
Normal file
29
src/router/modules/tree-table.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/** When your routing table is too long, you can split it into small modules**/
|
||||||
|
|
||||||
|
import Layout from '@/layout/Layout'
|
||||||
|
|
||||||
|
const treeTableRouter = {
|
||||||
|
path: '/tree-table',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/table/complex-table',
|
||||||
|
name: 'TreeTable',
|
||||||
|
meta: {
|
||||||
|
title: 'treeTable',
|
||||||
|
icon: 'tree-table'
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'index',
|
||||||
|
component: () => import('@/views/tree-table/index'),
|
||||||
|
name: 'TreeTableDemo',
|
||||||
|
meta: { title: 'treeTable' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'custom',
|
||||||
|
component: () => import('@/views/tree-table/custom'),
|
||||||
|
name: 'CustomTreeTableDemo',
|
||||||
|
meta: { title: 'customTreeTable' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
export default treeTableRouter
|
@@ -1,8 +1,4 @@
|
|||||||
import variables from '@/styles/element-variables.scss'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
theme: variables.theme,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {boolean} true | false
|
* @type {boolean} true | false
|
||||||
* @description Whether show the settings right-panel
|
* @description Whether show the settings right-panel
|
||||||
|
@@ -1,8 +1,7 @@
|
|||||||
import defaultSettings from '@/settings'
|
import defaultSettings from '@/settings'
|
||||||
const { showSettings, tagsView, fixedHeader, sidebarLogo, theme } = defaultSettings
|
const { showSettings, tagsView, fixedHeader, sidebarLogo } = defaultSettings
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
theme: theme,
|
|
||||||
showSettings: showSettings,
|
showSettings: showSettings,
|
||||||
tagsView: tagsView,
|
tagsView: tagsView,
|
||||||
fixedHeader: fixedHeader,
|
fixedHeader: fixedHeader,
|
||||||
|
@@ -23,9 +23,3 @@ $--table-border:1px solid#dfe6ec;
|
|||||||
$--font-path: '~element-ui/lib/theme-chalk/fonts';
|
$--font-path: '~element-ui/lib/theme-chalk/fonts';
|
||||||
|
|
||||||
@import "~element-ui/packages/theme-chalk/src/index";
|
@import "~element-ui/packages/theme-chalk/src/index";
|
||||||
|
|
||||||
// the :export directive is the magic sauce for webpack
|
|
||||||
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
|
|
||||||
:export {
|
|
||||||
theme: $--color-primary;
|
|
||||||
}
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { MessageBox, Message } from 'element-ui'
|
import { Message } from 'element-ui'
|
||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
import { getToken } from '@/utils/auth'
|
import { getToken } from '@/utils/auth'
|
||||||
|
|
||||||
@@ -33,39 +33,40 @@ service.interceptors.response.use(
|
|||||||
* If you want to get information such as headers or status
|
* If you want to get information such as headers or status
|
||||||
* Please return response => response
|
* Please return response => response
|
||||||
*/
|
*/
|
||||||
|
response => response.data,
|
||||||
/**
|
/**
|
||||||
* 下面的注释为通过在response里,自定义code来标示请求状态
|
* 下面的注释为通过在response里,自定义code来标示请求状态
|
||||||
* 当code返回如下情况则说明权限有问题,登出并返回到登录页
|
* 当code返回如下情况则说明权限有问题,登出并返回到登录页
|
||||||
* 如想通过 XMLHttpRequest 来状态码标识 逻辑可写在下面error中
|
* 如想通过 xmlhttprequest 来状态码标识 逻辑可写在下面error中
|
||||||
* 以下代码均为样例,请结合自生需求加以修改,若不需要,则可删除
|
* 以下代码均为样例,请结合自生需求加以修改,若不需要,则可删除
|
||||||
*/
|
*/
|
||||||
response => {
|
// response => {
|
||||||
const res = response.data
|
// const res = response.data
|
||||||
if (res.code !== 20000) {
|
// if (res.code !== 20000) {
|
||||||
Message({
|
// Message({
|
||||||
message: res.message,
|
// message: res.message,
|
||||||
type: 'error',
|
// type: 'error',
|
||||||
duration: 5 * 1000
|
// duration: 5 * 1000
|
||||||
})
|
// })
|
||||||
// 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了;
|
// // 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了;
|
||||||
if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
|
// if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
|
||||||
// 请自行在引入 MessageBox
|
// // 请自行在引入 MessageBox
|
||||||
// import { Message, MessageBox } from 'element-ui'
|
// // import { Message, MessageBox } from 'element-ui'
|
||||||
MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', {
|
// MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', {
|
||||||
confirmButtonText: '重新登录',
|
// confirmButtonText: '重新登录',
|
||||||
cancelButtonText: '取消',
|
// cancelButtonText: '取消',
|
||||||
type: 'warning'
|
// type: 'warning'
|
||||||
}).then(() => {
|
// }).then(() => {
|
||||||
store.dispatch('user/resetToken').then(() => {
|
// store.dispatch('user/resetToken').then(() => {
|
||||||
location.reload() // 为了重新实例化vue-router对象 避免bug
|
// location.reload() // 为了重新实例化vue-router对象 避免bug
|
||||||
})
|
// })
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
return Promise.reject('error')
|
// return Promise.reject('error')
|
||||||
} else {
|
// } else {
|
||||||
return res
|
// return response.data
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
error => {
|
error => {
|
||||||
console.log('err' + error) // for debug
|
console.log('err' + error) // for debug
|
||||||
Message({
|
Message({
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<sticky :z-index="10" class-name="sub-navbar">
|
<sticky class-name="sub-navbar">
|
||||||
<el-dropdown trigger="click">
|
<el-dropdown trigger="click">
|
||||||
<el-button plain>
|
<el-button plain>
|
||||||
Platform<i class="el-icon-caret-bottom el-icon--right" />
|
Platform<i class="el-icon-caret-bottom el-icon--right" />
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="createPost-container">
|
<div class="createPost-container">
|
||||||
<el-form ref="postForm" :model="postForm" :rules="rules" class="form-container">
|
<el-form ref="postForm" :model="postForm" :rules="rules" class="form-container">
|
||||||
<sticky :z-index="10" :class-name="'sub-navbar '+postForm.status">
|
<sticky :class-name="'sub-navbar '+postForm.status">
|
||||||
<CommentDropdown v-model="postForm.comment_disabled" />
|
<CommentDropdown v-model="postForm.comment_disabled" />
|
||||||
<PlatformDropdown v-model="postForm.platforms" />
|
<PlatformDropdown v-model="postForm.platforms" />
|
||||||
<SourceUrlDropdown v-model="postForm.source_uri" />
|
<SourceUrlDropdown v-model="postForm.source_uri" />
|
||||||
@@ -81,7 +81,7 @@ import MDinput from '@/components/MDinput'
|
|||||||
import Sticky from '@/components/Sticky' // 粘性header组件
|
import Sticky from '@/components/Sticky' // 粘性header组件
|
||||||
import { validURL } from '@/utils/validate'
|
import { validURL } from '@/utils/validate'
|
||||||
import { fetchArticle } from '@/api/article'
|
import { fetchArticle } from '@/api/article'
|
||||||
import { searchUser } from '@/api/remoteSearch'
|
import { userSearch } from '@/api/remoteSearch'
|
||||||
import Warning from './Warning'
|
import Warning from './Warning'
|
||||||
import { CommentDropdown, PlatformDropdown, SourceUrlDropdown } from './Dropdown'
|
import { CommentDropdown, PlatformDropdown, SourceUrlDropdown } from './Dropdown'
|
||||||
|
|
||||||
@@ -225,7 +225,7 @@ export default {
|
|||||||
this.postForm.status = 'draft'
|
this.postForm.status = 'draft'
|
||||||
},
|
},
|
||||||
getRemoteUserList(query) {
|
getRemoteUserList(query) {
|
||||||
searchUser(query).then(response => {
|
userSearch(query).then(response => {
|
||||||
if (!response.data.items) return
|
if (!response.data.items) return
|
||||||
this.userListOptions = response.data.items.map(v => v.name)
|
this.userListOptions = response.data.items.map(v => v.name)
|
||||||
})
|
})
|
||||||
|
@@ -95,6 +95,14 @@ export default {
|
|||||||
this.total = response.data.total
|
this.total = response.data.total
|
||||||
this.listLoading = false
|
this.listLoading = false
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
handleSizeChange(val) {
|
||||||
|
this.listQuery.limit = val
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
handleCurrentChange(val) {
|
||||||
|
this.listQuery.page = val
|
||||||
|
this.getList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -14,7 +14,6 @@
|
|||||||
<svg-icon icon-class="user" />
|
<svg-icon icon-class="user" />
|
||||||
</span>
|
</span>
|
||||||
<el-input
|
<el-input
|
||||||
ref="username"
|
|
||||||
v-model="loginForm.username"
|
v-model="loginForm.username"
|
||||||
:placeholder="$t('login.username')"
|
:placeholder="$t('login.username')"
|
||||||
name="username"
|
name="username"
|
||||||
@@ -28,8 +27,6 @@
|
|||||||
<svg-icon icon-class="password" />
|
<svg-icon icon-class="password" />
|
||||||
</span>
|
</span>
|
||||||
<el-input
|
<el-input
|
||||||
:key="passwordType"
|
|
||||||
ref="password"
|
|
||||||
v-model="loginForm.password"
|
v-model="loginForm.password"
|
||||||
:type="passwordType"
|
:type="passwordType"
|
||||||
:placeholder="$t('login.password')"
|
:placeholder="$t('login.password')"
|
||||||
@@ -100,7 +97,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
loginForm: {
|
loginForm: {
|
||||||
username: 'admin',
|
username: 'admin',
|
||||||
password: '111111'
|
password: '1111111'
|
||||||
},
|
},
|
||||||
loginRules: {
|
loginRules: {
|
||||||
username: [{ required: true, trigger: 'blur', validator: validateUsername }],
|
username: [{ required: true, trigger: 'blur', validator: validateUsername }],
|
||||||
@@ -123,13 +120,6 @@ export default {
|
|||||||
created() {
|
created() {
|
||||||
// window.addEventListener('storage', this.afterQRScan)
|
// window.addEventListener('storage', this.afterQRScan)
|
||||||
},
|
},
|
||||||
mounted() {
|
|
||||||
if (this.loginForm.username === '') {
|
|
||||||
this.$refs.username.focus()
|
|
||||||
} else if (this.loginForm.password === '') {
|
|
||||||
this.$refs.password.focus()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
destroyed() {
|
destroyed() {
|
||||||
// window.removeEventListener('storage', this.afterQRScan)
|
// window.removeEventListener('storage', this.afterQRScan)
|
||||||
},
|
},
|
||||||
@@ -140,9 +130,6 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
this.passwordType = 'password'
|
this.passwordType = 'password'
|
||||||
}
|
}
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$refs.password.focus()
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
handleLogin() {
|
handleLogin() {
|
||||||
this.$refs.loginForm.validate(valid => {
|
this.$refs.loginForm.validate(valid => {
|
||||||
@@ -189,12 +176,16 @@ export default {
|
|||||||
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
|
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
|
||||||
|
|
||||||
$bg:#283443;
|
$bg:#283443;
|
||||||
$light_gray:#fff;
|
$light_gray:#eee;
|
||||||
$cursor: #fff;
|
$cursor: #fff;
|
||||||
|
|
||||||
@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
|
@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
|
||||||
.login-container .el-input input {
|
.login-container .el-input input {
|
||||||
color: $cursor;
|
color: $cursor;
|
||||||
|
|
||||||
|
&::first-line {
|
||||||
|
color: $light_gray;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,7 +207,7 @@ $cursor: #fff;
|
|||||||
caret-color: $cursor;
|
caret-color: $cursor;
|
||||||
|
|
||||||
&:-webkit-autofill {
|
&:-webkit-autofill {
|
||||||
box-shadow: 0 0 0px 1000px $bg inset !important;
|
-webkit-box-shadow: 0 0 0px 1000px $bg inset !important;
|
||||||
-webkit-text-fill-color: $cursor !important;
|
-webkit-text-fill-color: $cursor !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
51
src/views/tree-table/custom/data.js
Normal file
51
src/views/tree-table/custom/data.js
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
const data = [
|
||||||
|
{
|
||||||
|
name: '1',
|
||||||
|
timeLine: 100,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: '1-1',
|
||||||
|
timeLine: 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '1-2',
|
||||||
|
timeLine: 60,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: '1-2-1',
|
||||||
|
timeLine: 35
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '1-2-2',
|
||||||
|
timeLine: 25
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '2',
|
||||||
|
timeLine: 80,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: '2-1',
|
||||||
|
timeLine: 30
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '2-2',
|
||||||
|
timeLine: 50
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '2-3',
|
||||||
|
timeLine: 60
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '3',
|
||||||
|
timeLine: 40
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
export default data
|
||||||
|
|
159
src/views/tree-table/custom/index.vue
Normal file
159
src/views/tree-table/custom/index.vue
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-button type="primary" size="small" style="margin:0 0 20px 0;">
|
||||||
|
<a href="https://github.com/PanJiaChen/vue-element-admin/tree/master/src/components/TreeTable" target="_blank">Documentation</a>
|
||||||
|
</el-button>
|
||||||
|
|
||||||
|
<tree-table
|
||||||
|
ref="TreeTable"
|
||||||
|
:data="tableData"
|
||||||
|
:default-expand-all="true"
|
||||||
|
:columns="columns"
|
||||||
|
border
|
||||||
|
default-children="children"
|
||||||
|
@selection-change="selectChange"
|
||||||
|
>
|
||||||
|
<template slot="selection">
|
||||||
|
<el-table-column type="selection" align="center" width="55" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template slot="pre-column">
|
||||||
|
<el-table-column type="expand" width="55">
|
||||||
|
<template>
|
||||||
|
<el-tag type="info">
|
||||||
|
Here is just a placeholder slot, you can display anything.
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template slot="timeline" slot-scope="{scope}">
|
||||||
|
<el-tooltip :content="scope.row.timeLine+'ms'" effect="dark" placement="left">
|
||||||
|
<div class="processContainer">
|
||||||
|
<div
|
||||||
|
:style="{ width:(scope.row.timeLine||0) * 3+'px',
|
||||||
|
background:scope.row.timeLine>50?'rgba(233,0,0,.5)':'rgba(0,0,233,0.5)',
|
||||||
|
marginLeft:scope.row._level * 50+'px' }"
|
||||||
|
class="process"
|
||||||
|
>
|
||||||
|
<span style="display:inline-block" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template slot="append" slot-scope="{scope}">
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="primary"
|
||||||
|
@click="addMenuItem(scope.row,'brother')"
|
||||||
|
>
|
||||||
|
Append Brother
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="primary"
|
||||||
|
@click="addMenuItem(scope.row,'children')"
|
||||||
|
>
|
||||||
|
Append Child
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
<template slot="operation" slot-scope="{scope}">
|
||||||
|
<el-button size="mini" type="success" @click="editItem(scope.row)">
|
||||||
|
Edit
|
||||||
|
</el-button>
|
||||||
|
<el-button size="mini" type="danger" @click="deleteItem(scope.row)">
|
||||||
|
Delete
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</tree-table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-dialog :visible.sync="dialogFormVisible" title="Edit">
|
||||||
|
<el-form :model="tempItem" label-width="100px" style="width:600px">
|
||||||
|
<el-form-item label="Name">
|
||||||
|
<el-input v-model.trim="tempItem.name" placeholder="Name" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<span slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="dialogFormVisible = false">Cancel</el-button>
|
||||||
|
<el-button type="primary" @click="updateItem">Confirm</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import TreeTable from '@/components/TreeTable'
|
||||||
|
import data from './data.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: { TreeTable },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tableData: [],
|
||||||
|
tempItem: {},
|
||||||
|
dialogFormVisible: false,
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
label: 'Name',
|
||||||
|
key: 'name',
|
||||||
|
expand: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Timeline',
|
||||||
|
key: 'timeline'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Append',
|
||||||
|
key: 'append',
|
||||||
|
width: 300
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Operation',
|
||||||
|
key: 'operation',
|
||||||
|
width: 160
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getData()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getData() {
|
||||||
|
this.tableData = data
|
||||||
|
},
|
||||||
|
editItem(row) {
|
||||||
|
this.tempItem = Object.assign({}, row)
|
||||||
|
this.dialogFormVisible = true
|
||||||
|
},
|
||||||
|
async updateItem() {
|
||||||
|
await this.$refs.TreeTable.updateTreeNode(this.tempItem)
|
||||||
|
this.dialogFormVisible = false
|
||||||
|
},
|
||||||
|
addMenuItem(row, type) {
|
||||||
|
if (type === 'children') {
|
||||||
|
this.$refs.TreeTable.addChild(row, { name: 'child', timeLine: this.randomNum() })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'brother') {
|
||||||
|
this.$refs.TreeTable.addBrother(row, { name: 'brother', timeLine: this.randomNum() })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deleteItem(row) {
|
||||||
|
this.$refs.TreeTable.delete(row)
|
||||||
|
},
|
||||||
|
selectChange(val) {
|
||||||
|
console.log(val)
|
||||||
|
},
|
||||||
|
randomNum() {
|
||||||
|
// return 1~100
|
||||||
|
const max = 100
|
||||||
|
const min = 1
|
||||||
|
return Math.floor(Math.random() * (max - min + 1) + min)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
80
src/views/tree-table/data.js
Normal file
80
src/views/tree-table/data.js
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
|
||||||
|
const data = [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
event: 'Event-0',
|
||||||
|
timeLine: 50
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
event: 'Event-1',
|
||||||
|
timeLine: 100,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
event: 'Event-2',
|
||||||
|
timeLine: 10
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
event: 'Event-3',
|
||||||
|
timeLine: 90,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
event: 'Event-4',
|
||||||
|
timeLine: 5
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
event: 'Event-5',
|
||||||
|
timeLine: 10
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
event: 'Event-6',
|
||||||
|
timeLine: 75,
|
||||||
|
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
event: 'Event-7',
|
||||||
|
timeLine: 50,
|
||||||
|
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: 71,
|
||||||
|
event: 'Event-7-1',
|
||||||
|
timeLine: 25
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 72,
|
||||||
|
event: 'Event-7-2',
|
||||||
|
timeLine: 5
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 73,
|
||||||
|
event: 'Event-7-3',
|
||||||
|
timeLine: 20
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
event: 'Event-8',
|
||||||
|
timeLine: 25
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
export default data
|
126
src/views/tree-table/index.vue
Normal file
126
src/views/tree-table/index.vue
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<div style="margin-bottom:20px;">
|
||||||
|
<el-button type="primary" size="small" class="option-item">
|
||||||
|
<a href="https://github.com/PanJiaChen/vue-element-admin/tree/master/src/components/TreeTable" target="_blank">Documentation</a>
|
||||||
|
</el-button>
|
||||||
|
|
||||||
|
<div class="option-item">
|
||||||
|
<el-tag>Expand All</el-tag>
|
||||||
|
<el-switch
|
||||||
|
v-model="defaultExpandAll"
|
||||||
|
active-color="#13ce66"
|
||||||
|
inactive-color="#ff4949"
|
||||||
|
@change="reset"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="option-item">
|
||||||
|
<el-tag>Show Checkbox</el-tag>
|
||||||
|
<el-switch
|
||||||
|
v-model="showCheckbox"
|
||||||
|
active-color="#13ce66"
|
||||||
|
inactive-color="#ff4949"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<tree-table :key="key" :default-expand-all="defaultExpandAll" :data="data" :columns="columns" border>
|
||||||
|
<template slot="scope" slot-scope="{scope}">
|
||||||
|
<el-tag>level: {{ scope.row._level }}</el-tag>
|
||||||
|
<el-tag>expand: {{ scope.row._expand }}</el-tag>
|
||||||
|
<el-tag>select: {{ scope.row._select }}</el-tag>
|
||||||
|
</template>
|
||||||
|
<template slot="operation" slot-scope="{scope}">
|
||||||
|
<el-button type="primary" size="" @click="click(scope)">
|
||||||
|
Click
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</tree-table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import treeTable from '@/components/TreeTable'
|
||||||
|
import data from './data'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'TreeTableDemo',
|
||||||
|
components: { treeTable },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
defaultExpandAll: false,
|
||||||
|
showCheckbox: true,
|
||||||
|
key: 1,
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
label: 'Checkbox',
|
||||||
|
checkbox: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
key: 'id',
|
||||||
|
expand: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Event',
|
||||||
|
key: 'event',
|
||||||
|
width: 200,
|
||||||
|
align: 'left'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Scope',
|
||||||
|
key: 'scope'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Operation',
|
||||||
|
key: 'operation'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
data: data
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
showCheckbox(val) {
|
||||||
|
if (val) {
|
||||||
|
this.columns.unshift({
|
||||||
|
label: 'Checkbox',
|
||||||
|
checkbox: true
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.columns.shift()
|
||||||
|
}
|
||||||
|
this.reset()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
reset() {
|
||||||
|
++this.key
|
||||||
|
},
|
||||||
|
click(scope) {
|
||||||
|
console.log(scope)
|
||||||
|
|
||||||
|
const row = scope.row
|
||||||
|
const message = Object.keys(row)
|
||||||
|
.map(i => {
|
||||||
|
return `<p>${i}: ${row[i]}</p>`
|
||||||
|
})
|
||||||
|
.join('')
|
||||||
|
|
||||||
|
this.$notify({
|
||||||
|
title: 'Success',
|
||||||
|
dangerouslyUseHTMLString: true,
|
||||||
|
message: message,
|
||||||
|
type: 'success'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.option-item{
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
</style>
|
@@ -1,22 +1,23 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const pkg = require('./package.json')
|
|
||||||
|
|
||||||
function resolve(dir) {
|
function resolve(dir) {
|
||||||
return path.join(__dirname, dir)
|
return path.join(__dirname, dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
const name = pkg.name || 'vue-element-admin' // page title
|
const name = 'vue-element-admin'
|
||||||
const port = 9527 // dev port
|
const port = 9527 // dev port
|
||||||
|
|
||||||
// All configuration item explanations can be find in https://cli.vuejs.org/config/
|
// Explanation of each configuration item You can find it in https://cli.vuejs.org/config/
|
||||||
module.exports = {
|
module.exports = {
|
||||||
/**
|
/**
|
||||||
* You will need to set publicPath if you plan to deploy your site under a sub path,
|
* You can set by yourself according to actual condition
|
||||||
* for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/,
|
* You will need to set this if you plan to deploy your site under a sub path,
|
||||||
* then publicPath should be set to "/bar/".
|
* 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 '/' !!!
|
* In most cases please use '/' !!!
|
||||||
* Detail: https://cli.vuejs.org/config/#publicpath
|
* Detail https://cli.vuejs.org/config/#publicPath
|
||||||
*/
|
*/
|
||||||
publicPath: '/',
|
publicPath: '/',
|
||||||
outputDir: 'dist',
|
outputDir: 'dist',
|
||||||
@@ -31,13 +32,11 @@ module.exports = {
|
|||||||
errors: true
|
errors: true
|
||||||
},
|
},
|
||||||
proxy: {
|
proxy: {
|
||||||
// change xxx-api/login => mock/login
|
'/api': {
|
||||||
// detail: https://cli.vuejs.org/config/#devserver-proxy
|
|
||||||
[process.env.VUE_APP_BASE_API]: {
|
|
||||||
target: `http://localhost:${port}/mock`,
|
target: `http://localhost:${port}/mock`,
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
pathRewrite: {
|
pathRewrite: {
|
||||||
['^' + process.env.VUE_APP_BASE_API]: ''
|
'^/api': ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -59,7 +58,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
configureWebpack: {
|
configureWebpack: {
|
||||||
// provide the app's title in webpack's name field, so that
|
// We provide the app's title in Webpack's name field, so that
|
||||||
// it can be accessed in index.html to inject the correct title.
|
// it can be accessed in index.html to inject the correct title.
|
||||||
name: name,
|
name: name,
|
||||||
resolve: {
|
resolve: {
|
||||||
@@ -71,8 +70,6 @@ module.exports = {
|
|||||||
chainWebpack(config) {
|
chainWebpack(config) {
|
||||||
config.plugins.delete('preload') // TODO: need test
|
config.plugins.delete('preload') // TODO: need test
|
||||||
config.plugins.delete('prefetch') // TODO: need test
|
config.plugins.delete('prefetch') // TODO: need test
|
||||||
|
|
||||||
// set svg-sprite-loader
|
|
||||||
config.module
|
config.module
|
||||||
.rule('svg')
|
.rule('svg')
|
||||||
.exclude.add(resolve('src/icons'))
|
.exclude.add(resolve('src/icons'))
|
||||||
@@ -88,8 +85,6 @@ module.exports = {
|
|||||||
symbolId: 'icon-[name]'
|
symbolId: 'icon-[name]'
|
||||||
})
|
})
|
||||||
.end()
|
.end()
|
||||||
|
|
||||||
// set preserveWhitespace
|
|
||||||
config.module
|
config.module
|
||||||
.rule('vue')
|
.rule('vue')
|
||||||
.use('vue-loader')
|
.use('vue-loader')
|
||||||
@@ -99,7 +94,6 @@ module.exports = {
|
|||||||
return options
|
return options
|
||||||
})
|
})
|
||||||
.end()
|
.end()
|
||||||
|
|
||||||
config
|
config
|
||||||
.when(process.env.NODE_ENV === 'development',
|
.when(process.env.NODE_ENV === 'development',
|
||||||
config => config.devtool('cheap-source-map')
|
config => config.devtool('cheap-source-map')
|
||||||
@@ -124,17 +118,17 @@ module.exports = {
|
|||||||
name: 'chunk-libs',
|
name: 'chunk-libs',
|
||||||
test: /[\\/]node_modules[\\/]/,
|
test: /[\\/]node_modules[\\/]/,
|
||||||
priority: 10,
|
priority: 10,
|
||||||
chunks: 'initial' // only package third parties that are initially dependent
|
chunks: 'initial' // 只打包初始时依赖的第三方
|
||||||
},
|
},
|
||||||
elementUI: {
|
elementUI: {
|
||||||
name: 'chunk-elementUI', // split elementUI into a single package
|
name: 'chunk-elementUI', // 单独将 elementUI 拆包
|
||||||
priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
|
priority: 20, // 权重要大于 libs 和 app 不然会被打包进 libs 或者 app
|
||||||
test: /[\\/]node_modules[\\/]element-ui[\\/]/
|
test: /[\\/]node_modules[\\/]element-ui[\\/]/
|
||||||
},
|
},
|
||||||
commons: {
|
commons: {
|
||||||
name: 'chunk-commons',
|
name: 'chunk-commons',
|
||||||
test: resolve('src/components'), // can customize your rules
|
test: resolve('src/components'), // 可自定义拓展你的规则
|
||||||
minChunks: 3, // minimum common number
|
minChunks: 3, // 最小公用次数
|
||||||
priority: 5,
|
priority: 5,
|
||||||
reuseExistingChunk: true
|
reuseExistingChunk: true
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user