├── .editorconfig
├── .gitignore
├── LICENSE
├── README.md
├── babel.config.js
├── deploy.sh
├── package.json
├── public
├── index.html
└── logo
│ └── umi-soft.svg
├── src
├── App.vue
├── api
│ ├── login.js
│ └── system-management
│ │ ├── dept.js
│ │ ├── deptRole.js
│ │ ├── dictionary.js
│ │ ├── group.js
│ │ ├── menu.js
│ │ ├── menuRole.js
│ │ ├── menuSecurity.js
│ │ ├── role.js
│ │ ├── roleGroup.js
│ │ ├── security.js
│ │ ├── user.js
│ │ ├── userDept.js
│ │ ├── userGroup.js
│ │ ├── userGroupRoleGroup.js
│ │ ├── userRole.js
│ │ └── userRoleGroup.js
├── assets
│ ├── custom-theme
│ │ ├── fonts
│ │ │ ├── element-icons.ttf
│ │ │ └── element-icons.woff
│ │ └── index.css
│ └── images
│ │ ├── 404.png
│ │ ├── 404_cloud.png
│ │ └── avatar.jpeg
├── components
│ ├── Abbreviation
│ │ └── index.vue
│ ├── Breadcrumb
│ │ └── index.vue
│ ├── ErrorPage
│ │ ├── 401.vue
│ │ └── 404.vue
│ ├── Hamburger
│ │ └── index.vue
│ ├── Redirect
│ │ └── index.vue
│ ├── Screenfull
│ │ └── index.vue
│ ├── ScrollPane
│ │ └── index.vue
│ └── SvgIcon
│ │ └── index.vue
├── directive
│ ├── clipboard
│ │ ├── clipboard.js
│ │ └── index.js
│ ├── el-dragDialog
│ │ ├── drag.js
│ │ └── index.js
│ └── permission
│ │ ├── index.js
│ │ └── permission.js
├── filters
│ └── index.js
├── icons
│ ├── index.js
│ ├── svg
│ │ ├── 404.svg
│ │ ├── add.svg
│ │ ├── captcha.svg
│ │ ├── check.svg
│ │ ├── del.svg
│ │ ├── dept.svg
│ │ ├── dictionary-multi.svg
│ │ ├── dictionary-setting.svg
│ │ ├── dictionary-single.svg
│ │ ├── dictionary-type.svg
│ │ ├── edit.svg
│ │ ├── eye.svg
│ │ ├── group.svg
│ │ ├── index.svg
│ │ ├── java.svg
│ │ ├── menu-setting.svg
│ │ ├── menu.svg
│ │ ├── password.svg
│ │ ├── role-setting.svg
│ │ ├── security.svg
│ │ ├── setting.svg
│ │ ├── user-group.svg
│ │ ├── user-role.svg
│ │ ├── user-setting.svg
│ │ ├── user.svg
│ │ └── utils.svg
│ └── svgo.yml
├── main.js
├── mock
│ ├── MockDB.js
│ ├── index.js
│ ├── login.js
│ ├── system-management
│ │ ├── dept.js
│ │ ├── deptRole.js
│ │ ├── dictionary.js
│ │ ├── group.js
│ │ ├── menu.js
│ │ ├── menuRole.js
│ │ ├── menuSecurity.js
│ │ ├── role.js
│ │ ├── roleGroup.js
│ │ ├── security.js
│ │ ├── user.js
│ │ ├── userDept.js
│ │ ├── userGroup.js
│ │ ├── userGroupRoleGroup.js
│ │ ├── userRole.js
│ │ └── userRoleGroup.js
│ └── utils.js
├── permission.js
├── router
│ ├── index.js
│ └── modules
│ │ ├── CodeGenerator.js
│ │ └── SystemManagement.js
├── store
│ ├── getters.js
│ ├── index.js
│ └── modules
│ │ ├── app.js
│ │ ├── dictionaries.js
│ │ ├── permission.js
│ │ ├── tagsView.js
│ │ └── user.js
├── styles
│ ├── element-ui.scss
│ ├── index.scss
│ ├── mixin.scss
│ └── transition.scss
├── utils
│ ├── auth.js
│ ├── clipboard.js
│ ├── index.js
│ ├── openWindow.js
│ ├── permission.js
│ ├── request.js
│ ├── scrollTo.js
│ └── validate.js
└── views
│ ├── code-generator
│ └── main.vue
│ ├── common
│ ├── components
│ │ ├── auditInfo
│ │ │ └── auditInfo.vue
│ │ ├── buttons
│ │ │ ├── ButtonRight.vue
│ │ │ └── NewLineButtonRight.vue
│ │ ├── dictionaryTranslates
│ │ │ └── State.vue
│ │ ├── formItemViews
│ │ │ ├── InputItemView.vue
│ │ │ └── TextItemView.vue
│ │ ├── layouts
│ │ │ ├── FlexCenter.vue
│ │ │ ├── FlexLeft.vue
│ │ │ └── FlexRight.vue
│ │ ├── paginations
│ │ │ └── pagination.vue
│ │ └── selects
│ │ │ └── SelectRight.vue
│ ├── index.js
│ └── mixins
│ │ ├── BaseEditForm.js
│ │ └── BaseQueryPageForm.js
│ ├── dashboard
│ └── index.vue
│ ├── layout
│ ├── LeftAccordionSidebar
│ │ ├── components
│ │ │ ├── AppMain.vue
│ │ │ ├── Navbar.vue
│ │ │ ├── Sidebar
│ │ │ │ ├── Item.vue
│ │ │ │ ├── Link.vue
│ │ │ │ ├── SidebarItem.vue
│ │ │ │ └── index.vue
│ │ │ ├── TagsView.vue
│ │ │ └── index.js
│ │ └── index.vue
│ └── MenuGroup
│ │ └── index.vue
│ ├── login
│ └── index.vue
│ └── system-management
│ ├── dept
│ ├── add.vue
│ ├── check.vue
│ ├── edit.vue
│ ├── main.vue
│ ├── mixins.js
│ └── query.vue
│ ├── dictionary-type
│ ├── add.vue
│ ├── check.vue
│ ├── edit.vue
│ ├── main.vue
│ ├── mixins.js
│ └── query.vue
│ ├── dictionary
│ ├── add.vue
│ ├── check.vue
│ ├── edit.vue
│ ├── mixins.js
│ ├── multiMain.vue
│ ├── multiQuery.vue
│ ├── singleMain.vue
│ └── singleQuery.vue
│ ├── group
│ ├── add.vue
│ ├── check.vue
│ ├── edit.vue
│ ├── main.vue
│ ├── mixins.js
│ └── query.vue
│ ├── menu
│ ├── check.vue
│ ├── edit.vue
│ ├── main.vue
│ ├── mixins.js
│ └── query.vue
│ ├── role
│ ├── add.vue
│ ├── check.vue
│ ├── edit.vue
│ ├── main.vue
│ ├── mixins.js
│ └── query.vue
│ ├── security
│ ├── add.vue
│ ├── check.vue
│ ├── edit.vue
│ ├── main.vue
│ ├── mixins.js
│ └── query.vue
│ └── user
│ ├── add.vue
│ ├── batchEdit.vue
│ ├── check.vue
│ ├── edit.vue
│ ├── main.vue
│ ├── mixins.js
│ ├── myself
│ └── modify.vue
│ └── query.vue
└── vue.config.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | end_of_line = lf
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
12 | [*.md]
13 | insert_final_newline = false
14 | trim_trailing_whitespace = false
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | dist/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | **/*.log
8 |
9 | test/unit/coverage
10 | test/e2e/reports
11 | selenium-debug.log
12 |
13 | # Editor directories and files
14 | .idea
15 | .vscode
16 | *.suo
17 | *.ntvs*
18 | *.njsproj
19 | *.sln
20 |
21 | package-lock.json
22 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017-present PanJiaChen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | ## Getting started
20 |
21 | ```bash
22 | # clone the project
23 | git clone https://github.com/umi-soft/element-admin.git
24 |
25 | # install dependency
26 | npm install
27 |
28 | # develop
29 | npm run dev
30 | ```
31 |
32 | ## Build
33 |
34 | ```bash
35 | # build for test environment
36 | npm run build:sit
37 |
38 | # build for production environment
39 | npm run build:prod
40 | ```
41 |
42 | ## Online
43 | [Preview](http://umi-soft.github.io/element-admin)
44 |
45 | ## Browsers support
46 |
47 | Modern browsers and Internet Explorer 10+.
48 |
49 | | [
](http://godban.github.io/browsers-support-badges/)IE / Edge | [
](http://godban.github.io/browsers-support-badges/)Firefox | [
](http://godban.github.io/browsers-support-badges/)Chrome | [
](http://godban.github.io/browsers-support-badges/)Safari |
50 | | --------- | --------- | --------- | --------- |
51 | | IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
52 |
53 | ## 2.x计划
54 |
55 | - 提供更多的页面布局模板,目前仅一种模板
56 | - 提供后端spring-boot开源工程
57 | - 微调数据库字段设计,比如废弃state字段,flag字段调整为deleted,增加后端API安全资源表等等
58 | - 升级vue-cli至3.x
59 |
60 | ## License
61 |
62 | [MIT](https://github.com/umi-soft/element-admin/blob/master/LICENSE)
63 |
64 | Copyright (c) 2018-present [一路向北](https://umi-soft.github.com)
65 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/app'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/deploy.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | # 确保脚本抛出遇到的错误
4 | set -e
5 |
6 | # 生成静态文件
7 | npm run build:prod
8 |
9 | # 进入生成的文件夹
10 | cd dist
11 |
12 | #创建.nojekyll 防止Github Pages build错误
13 | touch .nojekyll
14 |
15 | git init
16 | git add -A
17 | git commit -m 'deploy'
18 |
19 | git push -f "https://github.com/umi-soft/element-admin.git" master:gh-pages
20 |
21 | cd -
22 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "element-admin",
3 | "version": "1.0.5",
4 | "description": "基础",
5 | "author": "胡杰",
6 | "license": "MIT",
7 | "scripts": {
8 | "serve": "vue-cli-service serve",
9 | "build": "vue-cli-service build",
10 | "lint": "vue-cli-service lint",
11 | "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml"
12 | },
13 | "lint-staged": {
14 | "src/**/*.{js,vue}": [
15 | "eslint --fix",
16 | "git add"
17 | ]
18 | },
19 | "keywords": [
20 | "vue",
21 | "element-ui",
22 | "admin",
23 | "element-admin"
24 | ],
25 | "repository": {
26 | "type": "git",
27 | "url": "git+https://github.com/umi-soft/element-admin.git"
28 | },
29 | "bugs": {
30 | "url": "https://github.com/umi-soft/element-admin/issues"
31 | },
32 | "dependencies": {
33 | "axios": "0.18.0",
34 | "clipboard": "1.7.1",
35 | "element-ui": "2.4.6",
36 | "es6-uuid": "^1.0.1",
37 | "js-cookie": "2.2.0",
38 | "lodash": "^4.17.11",
39 | "mockjs": "1.0.1-beta3",
40 | "normalize.css": "7.0.0",
41 | "nprogress": "0.2.0",
42 | "path-to-regexp": "^2.4.0",
43 | "qs": "^6.6.0",
44 | "screenfull": "3.3.3",
45 | "svg-sprite-loader": "^4.1.3",
46 | "svgo": "1.0.5",
47 | "vue": "^2.5.22",
48 | "vue-count-to": "1.0.13",
49 | "vue-router": "3.0.1",
50 | "vue-splitpane": "1.0.2",
51 | "vuex": "3.0.1"
52 | },
53 | "devDependencies": {
54 | "@vue/cli-plugin-babel": "^3.4.0",
55 | "@vue/cli-plugin-eslint": "^3.4.0",
56 | "@vue/cli-service": "^3.4.0",
57 | "babel-eslint": "^10.0.1",
58 | "eslint": "^5.8.0",
59 | "eslint-plugin-vue": "^5.0.0",
60 | "node-sass": "^4.11.0",
61 | "sass-loader": "^7.1.0",
62 | "vue-template-compiler": "^2.5.21"
63 | },
64 | "eslintConfig": {
65 | "root": true,
66 | "env": {
67 | "node": true
68 | },
69 | "extends": [
70 | "plugin:vue/essential",
71 | "eslint:recommended"
72 | ],
73 | "rules": {
74 | "no-console": "off",
75 | "vue/no-use-v-if-with-v-for": "off"
76 | },
77 | "parserOptions": {
78 | "parser": "babel-eslint"
79 | }
80 | },
81 | "postcss": {
82 | "plugins": {
83 | "autoprefixer": {}
84 | }
85 | },
86 | "engines": {
87 | "node": ">= 6.0.0",
88 | "npm": ">= 3.0.0"
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | UMI-SOFT
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
--------------------------------------------------------------------------------
/src/api/login.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | const base_url = '/admin/auth/'
4 |
5 | export function captcha() {
6 | return request({
7 | url: base_url + 'captcha',
8 | method: 'get'
9 | })
10 | }
11 |
12 | export function loginByLoginName(data) {
13 | return request({
14 | url: base_url + 'login',
15 | method: 'post',
16 | data
17 | })
18 | }
19 |
20 | export function getUserInfo(token) {
21 | return request({
22 | url: base_url + 'user-authorities',
23 | method: 'get',
24 | data: { token }
25 | })
26 | }
27 |
28 | export function getRouterRoles(token) {
29 | return request({
30 | url: base_url + 'system-authorities',
31 | method: 'get',
32 | data: { token }
33 | })
34 | }
35 |
36 | export function logout(token) {
37 | return request({
38 | url: base_url + 'logout',
39 | method: 'get',
40 | data: { token }
41 | })
42 | }
43 |
--------------------------------------------------------------------------------
/src/api/system-management/dept.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | const base_url = '/admin/dept/'
4 |
5 | export function queryAllDepts(data) {
6 | return request({
7 | url: base_url + 'query-all',
8 | method: 'post',
9 | data
10 | })
11 | }
12 |
13 | export function queryAllTreeDepts(id) {
14 | return request({
15 | url: base_url + 'query-all-tree',
16 | method: 'get',
17 | data: { id }
18 | })
19 | }
20 |
21 | export function queryDeptById(id) {
22 | return request({
23 | url: base_url + 'query-by-id',
24 | method: 'get',
25 | data: { id }
26 | })
27 | }
28 |
29 | export function addDept(data) {
30 | return request({
31 | url: base_url + 'add',
32 | method: 'post',
33 | data
34 | })
35 | }
36 |
37 | export function editDept(data) {
38 | return request({
39 | url: base_url + 'edit',
40 | method: 'post',
41 | data
42 | })
43 | }
44 |
45 | export function delDept(id) {
46 | return request({
47 | url: base_url + 'del',
48 | method: 'post',
49 | data: { id }
50 | })
51 | }
52 |
53 | export function queryAllDeptUsers(id) {
54 | return request({
55 | url: base_url + 'all-users',
56 | method: 'get',
57 | data: { id }
58 | })
59 | }
60 |
61 | export function queryAllDeptRoles(id) {
62 | return request({
63 | url: base_url + 'all-roles',
64 | method: 'get',
65 | data: { id }
66 | })
67 | }
68 |
--------------------------------------------------------------------------------
/src/api/system-management/deptRole.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | const base_url = '/admin/dept-role/'
4 |
5 | export function add(data) {
6 | return request({
7 | url: base_url + 'add',
8 | method: 'post',
9 | data
10 | })
11 | }
12 |
13 | export function delByEntityMapping(data) {
14 | return request({
15 | url: base_url + 'del-by-entity-mapping',
16 | method: 'post',
17 | data
18 | })
19 | }
20 |
--------------------------------------------------------------------------------
/src/api/system-management/dictionary.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | const base_url = '/admin/dictionary/'
4 |
5 | export function queryPageDictionaries(data) {
6 | return request({
7 | url: base_url + 'query-page',
8 | method: 'post',
9 | data
10 | })
11 | }
12 |
13 | export function queryAllDictionaries(data) {
14 | return request({
15 | url: base_url + 'query-all',
16 | method: 'post',
17 | data
18 | })
19 | }
20 |
21 | export function queryDictionaryById(id) {
22 | return request({
23 | url: base_url + 'query-by-id',
24 | method: 'get',
25 | data: { id }
26 | })
27 | }
28 |
29 | export function addDictionary(data) {
30 | return request({
31 | url: base_url + 'add',
32 | method: 'post',
33 | data
34 | })
35 | }
36 |
37 | export function editDictionary(data) {
38 | return request({
39 | url: base_url + 'edit',
40 | method: 'post',
41 | data
42 | })
43 | }
44 |
45 | export function delDictionary(id) {
46 | return request({
47 | url: base_url + 'del',
48 | method: 'post',
49 | data: { id }
50 | })
51 | }
52 |
--------------------------------------------------------------------------------
/src/api/system-management/group.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | const base_url = '/admin/group/'
4 |
5 | export function queryPageGroups(data) {
6 | return request({
7 | url: base_url + 'query-page',
8 | method: 'post',
9 | data
10 | })
11 | }
12 |
13 | export function queryAllGroups(data) {
14 | return request({
15 | url: base_url + 'query-all',
16 | method: 'post',
17 | data
18 | })
19 | }
20 |
21 | export function queryGroupById(id) {
22 | return request({
23 | url: base_url + 'query-by-id',
24 | method: 'get',
25 | data: { id }
26 | })
27 | }
28 |
29 | export function addGroup(data) {
30 | return request({
31 | url: base_url + 'add',
32 | method: 'post',
33 | data
34 | })
35 | }
36 |
37 | export function editGroup(data) {
38 | return request({
39 | url: base_url + 'edit',
40 | method: 'post',
41 | data
42 | })
43 | }
44 |
45 | export function delGroup(id) {
46 | return request({
47 | url: base_url + 'del',
48 | method: 'post',
49 | data: { id }
50 | })
51 | }
52 |
53 | export function queryAllRoleGroupUsers(id) {
54 | return request({
55 | url: base_url + 'all-role-group-users',
56 | method: 'get',
57 | data: { id }
58 | })
59 | }
60 |
61 | export function queryAllUserGroupUsers(id) {
62 | return request({
63 | url: base_url + 'all-user-group-users',
64 | method: 'get',
65 | data: { id }
66 | })
67 | }
68 |
69 | export function queryAllRoleGroups(id) {
70 | return request({
71 | url: base_url + 'all-role-groups',
72 | method: 'get',
73 | data: { id }
74 | })
75 | }
76 |
77 | export function queryAllUserGroups(id) {
78 | return request({
79 | url: base_url + 'all-user-groups',
80 | method: 'get',
81 | data: { id }
82 | })
83 | }
84 |
85 | export function queryAllGroupRoles(id) {
86 | return request({
87 | url: base_url + 'all-roles',
88 | method: 'get',
89 | data: { id }
90 | })
91 | }
92 |
--------------------------------------------------------------------------------
/src/api/system-management/menuRole.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | const base_url = '/admin/menu-role/'
4 |
5 | export function delByEntityMapping(data) {
6 | return request({
7 | url: base_url + 'del-by-entity-mapping',
8 | method: 'post',
9 | data
10 | })
11 | }
12 |
13 | export function reset(data) {
14 | return request({
15 | url: base_url + 'reset',
16 | method: 'post',
17 | data
18 | })
19 | }
20 |
--------------------------------------------------------------------------------
/src/api/system-management/menuSecurity.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | const base_url = '/admin/menu-security/'
4 |
5 | export function add(data) {
6 | return request({
7 | url: base_url + 'add',
8 | method: 'post',
9 | data
10 | })
11 | }
12 |
13 | export function delByEntityMapping(data) {
14 | return request({
15 | url: base_url + 'del-by-entity-mapping',
16 | method: 'post',
17 | data
18 | })
19 | }
20 |
--------------------------------------------------------------------------------
/src/api/system-management/role.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | const base_url = '/admin/role/'
4 |
5 | export function queryPageRoles(data) {
6 | return request({
7 | url: base_url + 'query-page',
8 | method: 'post',
9 | data
10 | })
11 | }
12 |
13 | export function queryAllRoles(data) {
14 | return request({
15 | url: base_url + 'query-all',
16 | method: 'post',
17 | data
18 | })
19 | }
20 |
21 | export function queryRoleById(id) {
22 | return request({
23 | url: base_url + 'query-by-id',
24 | method: 'get',
25 | data: { id }
26 | })
27 | }
28 |
29 | export function addRole(data) {
30 | return request({
31 | url: base_url + 'add',
32 | method: 'post',
33 | data
34 | })
35 | }
36 |
37 | export function editRole(data) {
38 | return request({
39 | url: base_url + 'edit',
40 | method: 'post',
41 | data
42 | })
43 | }
44 |
45 | export function delRole(id) {
46 | return request({
47 | url: base_url + 'del',
48 | method: 'post',
49 | data: { id }
50 | })
51 | }
52 |
53 | export function queryAllRoleMenus(id) {
54 | return request({
55 | url: base_url + 'all-menus',
56 | method: 'get',
57 | data: { id }
58 | })
59 | }
60 |
61 | export function queryAllRoleUsers(id) {
62 | return request({
63 | url: base_url + 'all-users',
64 | method: 'get',
65 | data: { id }
66 | })
67 | }
68 |
69 | export function queryAllRoleDepts(id) {
70 | return request({
71 | url: base_url + 'all-depts',
72 | method: 'get',
73 | data: { id }
74 | })
75 | }
76 |
77 | export function queryAllRoleGroups(id) {
78 | return request({
79 | url: base_url + 'all-role-groups',
80 | method: 'get',
81 | data: { id }
82 | })
83 | }
84 |
--------------------------------------------------------------------------------
/src/api/system-management/roleGroup.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | const base_url = '/admin/role-group/'
4 |
5 | export function add(data) {
6 | return request({
7 | url: base_url + 'add',
8 | method: 'post',
9 | data
10 | })
11 | }
12 |
13 | export function reset(data) {
14 | return request({
15 | url: base_url + 'reset',
16 | method: 'post',
17 | data
18 | })
19 | }
20 |
21 | export function delByEntityMapping(data) {
22 | return request({
23 | url: base_url + 'del-by-entity-mapping',
24 | method: 'post',
25 | data
26 | })
27 | }
28 |
--------------------------------------------------------------------------------
/src/api/system-management/security.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | const base_url = '/admin/security/'
4 |
5 | export function queryPage(data) {
6 | return request({
7 | url: base_url + 'query-page',
8 | method: 'post',
9 | data
10 | })
11 | }
12 |
13 | export function queryAll(data) {
14 | return request({
15 | url: base_url + 'query-all',
16 | method: 'post',
17 | data
18 | })
19 | }
20 |
21 | export function queryById(id) {
22 | return request({
23 | url: base_url + 'query-by-id',
24 | method: 'get',
25 | data: { id }
26 | })
27 | }
28 |
29 | export function add(data) {
30 | return request({
31 | url: base_url + 'add',
32 | method: 'post',
33 | data
34 | })
35 | }
36 |
37 | export function edit(data) {
38 | return request({
39 | url: base_url + 'edit',
40 | method: 'post',
41 | data
42 | })
43 | }
44 |
45 | export function del(id) {
46 | return request({
47 | url: base_url + 'del',
48 | method: 'post',
49 | data: { id }
50 | })
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/src/api/system-management/user.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | const base_url = '/admin/user/'
4 |
5 | export function queryPageUsers(data) {
6 | return request({
7 | url: base_url + 'query-page',
8 | method: 'post',
9 | data
10 | })
11 | }
12 |
13 | export function queryUserById(id) {
14 | return request({
15 | url: base_url + 'query-by-id',
16 | method: 'get',
17 | data: { id }
18 | })
19 | }
20 |
21 | export function checkLoginName(data) {
22 | return request({
23 | url: base_url + 'check-login-name',
24 | method: 'post',
25 | data
26 | })
27 | }
28 |
29 | export const uploadAvatar = base_url + 'upload-avatar'
30 | export const previewAvatar = base_url + 'avatar/'
31 |
32 | export function addUser(data) {
33 | return request({
34 | url: base_url + 'add',
35 | method: 'post',
36 | data
37 | })
38 | }
39 |
40 | export function editUser(data) {
41 | return request({
42 | url: base_url + 'edit',
43 | method: 'post',
44 | data
45 | })
46 | }
47 |
48 | export function editUserPassword(data) {
49 | return request({
50 | url: base_url + 'edit-password',
51 | method: 'post',
52 | data
53 | })
54 | }
55 |
56 | export function delUser(id) {
57 | return request({
58 | url: base_url + 'del',
59 | method: 'post',
60 | data: { id }
61 | })
62 | }
63 |
64 | export function queryAllUserRoles(params) {
65 | return request({
66 | url: base_url + 'all-roles',
67 | method: 'get',
68 | data: params
69 | })
70 | }
71 |
72 | export function queryAllUserDepts(params) {
73 | return request({
74 | url: base_url + 'all-depts',
75 | method: 'get',
76 | data: params
77 | })
78 | }
79 |
80 | export function queryAllUserGroups(params) {
81 | return request({
82 | url: base_url + 'all-user-groups',
83 | method: 'get',
84 | data: params
85 | })
86 | }
87 |
88 | export function queryAllUserRoleGroups(params) {
89 | return request({
90 | url: base_url + 'all-role-groups',
91 | method: 'get',
92 | data: params
93 | })
94 | }
95 |
--------------------------------------------------------------------------------
/src/api/system-management/userDept.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | const base_url = '/admin/user-dept/'
4 |
5 | export function add(data) {
6 | return request({
7 | url: base_url + 'add',
8 | method: 'post',
9 | data
10 | })
11 | }
12 |
13 | export function reset(data) {
14 | return request({
15 | url: base_url + 'reset',
16 | method: 'post',
17 | data
18 | })
19 | }
20 |
21 | export function delByEntityMapping(data) {
22 | return request({
23 | url: base_url + 'del-by-entity-mapping',
24 | method: 'post',
25 | data
26 | })
27 | }
28 |
--------------------------------------------------------------------------------
/src/api/system-management/userGroup.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | const base_url = '/admin/user-group/'
4 |
5 | export function add(data) {
6 | return request({
7 | url: base_url + 'add',
8 | method: 'post',
9 | data
10 | })
11 | }
12 |
13 | export function reset(data) {
14 | return request({
15 | url: base_url + 'reset',
16 | method: 'post',
17 | data
18 | })
19 | }
20 |
21 | export function delByEntityMapping(data) {
22 | return request({
23 | url: base_url + 'del-by-entity-mapping',
24 | method: 'post',
25 | data
26 | })
27 | }
28 |
--------------------------------------------------------------------------------
/src/api/system-management/userGroupRoleGroup.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | const base_url = '/admin/user-group-role-group/'
4 |
5 | export function add(data) {
6 | return request({
7 | url: base_url + 'add',
8 | method: 'post',
9 | data
10 | })
11 | }
12 |
13 | export function delByEntityMapping(data) {
14 | return request({
15 | url: base_url + 'del-by-entity-mapping',
16 | method: 'post',
17 | data
18 | })
19 | }
20 |
--------------------------------------------------------------------------------
/src/api/system-management/userRole.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | const base_url = '/admin/user-role/'
4 |
5 | export function add(data) {
6 | return request({
7 | url: base_url + 'add',
8 | method: 'post',
9 | data
10 | })
11 | }
12 |
13 | export function reset(data) {
14 | return request({
15 | url: base_url + 'reset',
16 | method: 'post',
17 | data
18 | })
19 | }
20 |
21 | export function delByEntityMapping(data) {
22 | return request({
23 | url: base_url + 'del-by-entity-mapping',
24 | method: 'post',
25 | data
26 | })
27 | }
28 |
--------------------------------------------------------------------------------
/src/api/system-management/userRoleGroup.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | const base_url = '/admin/user-role-group/'
4 |
5 | export function add(data) {
6 | return request({
7 | url: base_url + 'add',
8 | method: 'post',
9 | data
10 | })
11 | }
12 |
13 | export function reset(data) {
14 | return request({
15 | url: base_url + 'reset',
16 | method: 'post',
17 | data
18 | })
19 | }
20 |
21 | export function delByEntityMapping(data) {
22 | return request({
23 | url: base_url + 'del-by-entity-mapping',
24 | method: 'post',
25 | data
26 | })
27 | }
28 |
--------------------------------------------------------------------------------
/src/assets/custom-theme/fonts/element-icons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/umi-soft/element-admin/3c1b9b3fa74526df81c00a6c4685cac656b0efff/src/assets/custom-theme/fonts/element-icons.ttf
--------------------------------------------------------------------------------
/src/assets/custom-theme/fonts/element-icons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/umi-soft/element-admin/3c1b9b3fa74526df81c00a6c4685cac656b0efff/src/assets/custom-theme/fonts/element-icons.woff
--------------------------------------------------------------------------------
/src/assets/images/404.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/umi-soft/element-admin/3c1b9b3fa74526df81c00a6c4685cac656b0efff/src/assets/images/404.png
--------------------------------------------------------------------------------
/src/assets/images/404_cloud.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/umi-soft/element-admin/3c1b9b3fa74526df81c00a6c4685cac656b0efff/src/assets/images/404_cloud.png
--------------------------------------------------------------------------------
/src/assets/images/avatar.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/umi-soft/element-admin/3c1b9b3fa74526df81c00a6c4685cac656b0efff/src/assets/images/avatar.jpeg
--------------------------------------------------------------------------------
/src/components/Abbreviation/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ abbr }}
4 | {{ content }}
5 |
6 |
7 |
8 |
48 |
49 |
56 |
--------------------------------------------------------------------------------
/src/components/Breadcrumb/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ item.meta.title }}
6 | {{ item.meta.title }}
7 |
8 |
9 |
10 |
11 |
12 |
44 |
45 |
57 |
--------------------------------------------------------------------------------
/src/components/Hamburger/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
20 |
21 |
22 |
23 |
38 |
39 |
53 |
--------------------------------------------------------------------------------
/src/components/Redirect/index.vue:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/src/components/Screenfull/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
27 |
28 |
29 |
30 |
68 |
69 |
79 |
--------------------------------------------------------------------------------
/src/components/ScrollPane/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
24 |
25 |
41 |
--------------------------------------------------------------------------------
/src/components/SvgIcon/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
34 |
35 |
44 |
--------------------------------------------------------------------------------
/src/directive/clipboard/clipboard.js:
--------------------------------------------------------------------------------
1 | // Inspired by https://github.com/Inndy/vue-clipboard2
2 | const Clipboard = require('clipboard')
3 | if (!Clipboard) {
4 | throw new Error('you should npm install `clipboard` --save at first ')
5 | }
6 |
7 | export default {
8 | bind(el, binding) {
9 | if (binding.arg === 'success') {
10 | el._v_clipboard_success = binding.value
11 | } else if (binding.arg === 'error') {
12 | el._v_clipboard_error = binding.value
13 | } else {
14 | const clipboard = new Clipboard(el, {
15 | text() { return binding.value },
16 | action() { return binding.arg === 'cut' ? 'cut' : 'copy' }
17 | })
18 | clipboard.on('success', e => {
19 | const callback = el._v_clipboard_success
20 | callback && callback(e) // eslint-disable-line
21 | })
22 | clipboard.on('error', e => {
23 | const callback = el._v_clipboard_error
24 | callback && callback(e) // eslint-disable-line
25 | })
26 | el._v_clipboard = clipboard
27 | }
28 | },
29 | update(el, binding) {
30 | if (binding.arg === 'success') {
31 | el._v_clipboard_success = binding.value
32 | } else if (binding.arg === 'error') {
33 | el._v_clipboard_error = binding.value
34 | } else {
35 | el._v_clipboard.text = function() { return binding.value }
36 | el._v_clipboard.action = function() { return binding.arg === 'cut' ? 'cut' : 'copy' }
37 | }
38 | },
39 | unbind(el, binding) {
40 | if (binding.arg === 'success') {
41 | delete el._v_clipboard_success
42 | } else if (binding.arg === 'error') {
43 | delete el._v_clipboard_error
44 | } else {
45 | el._v_clipboard.destroy()
46 | delete el._v_clipboard
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/directive/clipboard/index.js:
--------------------------------------------------------------------------------
1 | import Clipboard from './clipboard'
2 |
3 | const install = function(Vue) {
4 | Vue.directive('Clipboard', Clipboard)
5 | }
6 |
7 | if (window.Vue) {
8 | window.clipboard = Clipboard
9 | Vue.use(install); // eslint-disable-line
10 | }
11 |
12 | Clipboard.install = install
13 | export default Clipboard
14 |
--------------------------------------------------------------------------------
/src/directive/el-dragDialog/drag.js:
--------------------------------------------------------------------------------
1 | export default{
2 | bind(el, binding, vnode) {
3 | const dialogHeaderEl = el.querySelector('.el-dialog__header')
4 | const dragDom = el.querySelector('.el-dialog')
5 | dialogHeaderEl.style.cssText += ';cursor:move;'
6 | dragDom.style.cssText += ';top:0px;'
7 |
8 | // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
9 | const getStyle = (function() {
10 | if (window.document.currentStyle) {
11 | return (dom, attr) => dom.currentStyle[attr]
12 | } else {
13 | return (dom, attr) => getComputedStyle(dom, false)[attr]
14 | }
15 | })()
16 |
17 | dialogHeaderEl.onmousedown = (e) => {
18 | // 鼠标按下,计算当前元素距离可视区的距离
19 | const disX = e.clientX - dialogHeaderEl.offsetLeft
20 | const disY = e.clientY - dialogHeaderEl.offsetTop
21 |
22 | const dragDomWidth = dragDom.offsetWidth
23 | const dragDomHeight = dragDom.offsetHeight
24 |
25 | const screenWidth = document.body.clientWidth
26 | const screenHeight = document.body.clientHeight
27 |
28 | const minDragDomLeft = dragDom.offsetLeft
29 | const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth
30 |
31 | const minDragDomTop = dragDom.offsetTop
32 | const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomHeight
33 |
34 | // 获取到的值带px 正则匹配替换
35 | let styL = getStyle(dragDom, 'left')
36 | let styT = getStyle(dragDom, 'top')
37 |
38 | if (styL.includes('%')) {
39 | styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100)
40 | styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100)
41 | } else {
42 | styL = +styL.replace(/\px/g, '')
43 | styT = +styT.replace(/\px/g, '')
44 | }
45 |
46 | document.onmousemove = function(e) {
47 | // 通过事件委托,计算移动的距离
48 | let left = e.clientX - disX
49 | let top = e.clientY - disY
50 |
51 | // 边界处理
52 | if (-(left) > minDragDomLeft) {
53 | left = -minDragDomLeft
54 | } else if (left > maxDragDomLeft) {
55 | left = maxDragDomLeft
56 | }
57 |
58 | if (-(top) > minDragDomTop) {
59 | top = -minDragDomTop
60 | } else if (top > maxDragDomTop) {
61 | top = maxDragDomTop
62 | }
63 |
64 | // 移动当前元素
65 | dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`
66 |
67 | // emit onDrag event
68 | vnode.child.$emit('dragDialog')
69 | }
70 |
71 | document.onmouseup = function(e) {
72 | document.onmousemove = null
73 | document.onmouseup = null
74 | }
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/directive/el-dragDialog/index.js:
--------------------------------------------------------------------------------
1 | import drag from './drag'
2 |
3 | const install = function(Vue) {
4 | Vue.directive('el-drag-dialog', drag)
5 | }
6 |
7 | if (window.Vue) {
8 | window['el-drag-dialog'] = drag
9 | Vue.use(install); // eslint-disable-line
10 | }
11 |
12 | drag.install = install
13 | export default drag
14 |
--------------------------------------------------------------------------------
/src/directive/permission/index.js:
--------------------------------------------------------------------------------
1 | import permission from './permission'
2 |
3 | const install = function(Vue) {
4 | Vue.directive('permission', permission)
5 | }
6 |
7 | if (window.Vue) {
8 | window['permission'] = permission
9 | Vue.use(install); // eslint-disable-line
10 | }
11 |
12 | permission.install = install
13 | export default permission
14 |
--------------------------------------------------------------------------------
/src/directive/permission/permission.js:
--------------------------------------------------------------------------------
1 |
2 | import store from '@/store'
3 |
4 | export default{
5 | inserted(el, binding, vnode) {
6 | const { value } = binding
7 | const roles = store.getters && store.getters.roles
8 |
9 | if (value && value instanceof Array && value.length > 0) {
10 | const permissionRoles = value
11 |
12 | const hasPermission = roles.some(role => {
13 | return permissionRoles.includes(role)
14 | })
15 |
16 | if (!hasPermission) {
17 | el.parentNode && el.parentNode.removeChild(el)
18 | }
19 | } else {
20 | throw new Error('权限不足')
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/filters/index.js:
--------------------------------------------------------------------------------
1 | import StoreDictionaries from '@/store/modules/dictionaries'
2 |
3 | // set function parseTime,formatTime to filter
4 | export { parseTime, formatTime } from '@/utils'
5 |
6 | /**
7 | * @param number
8 | * @param prefix 单位 ,如minute
9 | * @param suffix 复数单位结尾,默认是's'
10 | * @returns 为数值增加单位
11 | */
12 | function pluralize(number, prefix, suffix = 's') {
13 | if (number === 1) {
14 | return number + prefix
15 | }
16 | return number + prefix + suffix
17 | }
18 |
19 | /**
20 | * @param date 秒数(通常为后端时间戳)或Date对象
21 | * @returns {计算与当前时间差,并增加单位}
22 | */
23 | export function timeAgo(date) {
24 | let time = date
25 | if (typeof date === 'object') {
26 | time = date.getTime() / 1000
27 | }
28 | const between = Date.now() / 1000 - Number(time)
29 | if (between < 3600) {
30 | return pluralize(~~(between / 60), ' minute')
31 | } else if (between < 86400) {
32 | return pluralize(~~(between / 3600), ' hour')
33 | } else {
34 | return pluralize(~~(between / 86400), ' day')
35 | }
36 | }
37 |
38 | /**
39 | *
40 | * @param num
41 | * @param digits
42 | * @returns {string} 数字格式化
43 | */
44 | export function numberFormatter(num, digits) {
45 | const si = [
46 | { value: 1E18, symbol: 'E' },
47 | { value: 1E15, symbol: 'P' },
48 | { value: 1E12, symbol: 'T' },
49 | { value: 1E9, symbol: 'G' },
50 | { value: 1E6, symbol: 'M' },
51 | { value: 1E3, symbol: 'k' }
52 | ]
53 | for (let i = 0; i < si.length; i++) {
54 | if (num >= si[i].value) {
55 | return (num / si[i].value + 0.1).toFixed(digits).replace(/\.0+$|(\.[0-9]*[1-9])0+$/, '$1') + si[i].symbol
56 | }
57 | }
58 | return num.toString()
59 | }
60 |
61 | export function toThousandFilter(num) {
62 | return (+num || 0).toString().replace(/^-?\d+/g, m => m.replace(/(?=(?!\b)(\d{3})+$)/g, ','))
63 | }
64 |
65 | export function translateTrueOrFalse(state) {
66 | const dictionaries = StoreDictionaries.state.trueOrFalse
67 | const index = dictionaries.findIndex(item => { return '' + state === item.key + '' })
68 | return index === -1 ? '' : dictionaries[index].value
69 | }
70 |
71 | export function translateGender(state) {
72 | const dictionaries = StoreDictionaries.state.gender
73 | const index = dictionaries.findIndex(item => { return '' + state === item.key + '' })
74 | return index === -1 ? '' : dictionaries[index].value
75 | }
76 |
77 | export function translateDicCategory(category) {
78 | const dictionaries = StoreDictionaries.state.dictionaryCategory
79 | const index = dictionaries.findIndex(item => { return '' + category === item.key + '' })
80 | return index === -1 ? '' : dictionaries[index].value
81 | }
82 |
--------------------------------------------------------------------------------
/src/icons/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import SvgIcon from '@/components/SvgIcon'// svg组件
3 |
4 | // register globally
5 | Vue.component('svg-icon', SvgIcon)
6 |
7 | const req = require.context('./svg', false, /\.svg$/)
8 | const requireAll = requireContext => requireContext.keys().map(requireContext)
9 | requireAll(req)
10 |
--------------------------------------------------------------------------------
/src/icons/svg/404.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/add.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/captcha.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/check.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/del.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/dept.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/dictionary-multi.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/dictionary-single.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/dictionary-type.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/edit.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/eye.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/group.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/index.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/java.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/menu-setting.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/menu.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/password.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/role-setting.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/security.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/setting.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/user-group.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/user-setting.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/user.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/utils.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svgo.yml:
--------------------------------------------------------------------------------
1 | # replace default config
2 |
3 | # multipass: true
4 | # full: true
5 |
6 | plugins:
7 |
8 | # - name
9 | #
10 | # or:
11 | # - name: false
12 | # - name: true
13 | #
14 | # or:
15 | # - name:
16 | # param1: 1
17 | # param2: 2
18 |
19 | - removeAttrs:
20 | attrs:
21 | - 'fill'
22 | - 'fill-rule'
23 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 |
3 | import 'normalize.css/normalize.css'
4 |
5 | import Element from 'element-ui'
6 | import 'element-ui/lib/theme-chalk/index.css'
7 |
8 | import '@/styles/index.scss'
9 |
10 | import App from './App'
11 | import router from './router'
12 | import store from './store'
13 |
14 | import './icons'
15 | import './permission'
16 | import './mock'
17 |
18 | import components from './views/common'
19 | import * as filters from './filters'
20 |
21 | Vue.use(Element, {
22 | size: 'small'
23 | })
24 |
25 | // 全局注册组件
26 | Object.keys(components).forEach(key => {
27 | Vue.component(key, components[key])
28 | })
29 |
30 | // 全局注册指令
31 | Object.keys(filters).forEach(key => {
32 | Vue.filter(key, filters[key])
33 | })
34 |
35 | Vue.config.productionTip = false
36 |
37 | new Vue({
38 | el: '#app',
39 | router,
40 | store,
41 | render: h => h(App)
42 | })
43 |
--------------------------------------------------------------------------------
/src/mock/login.js:
--------------------------------------------------------------------------------
1 | import Mock from 'mockjs'
2 | import * as MockDB from './MockDB'
3 |
4 | let captcha = null
5 |
6 | export default {
7 | captcha: config => {
8 | console.log(config)
9 | captcha = Mock.mock({ 'number|1000-9999': 1000 }).number
10 | return {
11 | code: 1,
12 | data: Mock.Random.dataImage('448x47', captcha)
13 | }
14 | },
15 | loginByLoginName: config => {
16 | console.log(config)
17 | const params = JSON.parse(config.body)
18 | let token = null
19 | if ('' + captcha !== '' + params.captcha) {
20 | return {
21 | code: 1,
22 | data: {
23 | result: 2,
24 | message: '验证码错误'
25 | }
26 | }
27 | }
28 | if ((params.loginName === MockDB.simple.user.loginName && params.password !== MockDB.simple.user.password) || (params.loginName === MockDB.admin.user.loginName && params.password !== MockDB.admin.user.password)) {
29 | return {
30 | code: 1,
31 | data: {
32 | result: 3,
33 | message: '用户名或密码错误'
34 | }
35 | }
36 | }
37 | if (params.loginName === 'admin') {
38 | token = MockDB.admin.token
39 | } else {
40 | token = MockDB.simple.token
41 | }
42 | return {
43 | code: 1,
44 | data: {
45 | result: 1,
46 | message: '登录成功',
47 | token: token
48 | }
49 | }
50 | },
51 | getUserInfo: config => {
52 | console.log(config)
53 | return {
54 | code: 1,
55 | data: MockDB.admin
56 | }
57 | },
58 | getRouterRoles: () => {
59 | const routerRoles = new Map()
60 | routerRoles.set('90a127ce319d5d93b3b49c697cfa138f', ['simple'])
61 | // routerRoles.set('323c76618c6b56109bd490baf0d00902', ['simple'])
62 | routerRoles.set('f33d83225bef590d81f61a5afcbbca14', ['simple', 'others'])
63 | routerRoles.set('3de22ff390ab5d06bafcce547ff780bb', ['simple', 'others'])
64 | // routerRoles.set('8bdc5038a6585fd2b5d3ef7b1e4bf4e1', ['simple'])
65 | return {
66 | code: 1,
67 | data: routerRoles
68 | }
69 | },
70 | logout: () => {
71 | return {
72 | code: 1
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/mock/system-management/deptRole.js:
--------------------------------------------------------------------------------
1 | import * as MockDB from '../MockDB'
2 |
3 | export default {
4 | delByEntityMapping: config => {
5 | console.log(config)
6 | const params = JSON.parse(config.body)
7 | MockDB.deptRoles.splice(MockDB.deptRoles.findIndex(item => {
8 | return item.roleId === params.roleId && item.deptId === params.deptId
9 | }), 1)
10 | return {
11 | code: 1,
12 | message: '操作成功',
13 | data: ''
14 | }
15 | },
16 | add: config => {
17 | console.log(config)
18 | const params = JSON.parse(config.body)
19 | MockDB.deptRoles.push(params)
20 | return {
21 | code: 1,
22 | message: '操作成功',
23 | data: params
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/mock/system-management/dictionary.js:
--------------------------------------------------------------------------------
1 | import Mock from 'mockjs'
2 | import { param2Obj, deepMerge, deepClone, fieldQueryLike, sortArray } from '@/utils'
3 | import * as MockDB from '../MockDB'
4 |
5 | export default {
6 | queryPage: config => {
7 | console.log(config)
8 | const params = JSON.parse(config.body)
9 | const query = {}
10 | params.filters.forEach(filter => {
11 | query[filter.field] = filter.value
12 | })
13 | const queryResult = deepClone(fieldQueryLike(MockDB.dictionaries, query))
14 | params.sorts.forEach(sort => {
15 | // 前端目前无法实现多字段排序,因此排序以最后一个字段为准
16 | sortArray(queryResult, sort.field, sort.value === 'desc')
17 | })
18 | return {
19 | code: 1,
20 | message: '',
21 | data: {
22 | total: queryResult.length,
23 | pageSize: params.pageSize,
24 | page: params.page,
25 | list: queryResult.slice((params.page - 1) * params.pageSize, params.page * params.pageSize)
26 | }
27 | }
28 | },
29 | queryAll: config => {
30 | console.log(config)
31 | const params = JSON.parse(config.body)
32 | const query = {}
33 | params.filters.forEach(filter => {
34 | query[filter.field] = filter.value
35 | })
36 | const queryResult = deepClone(fieldQueryLike(MockDB.dictionaries, query))
37 | params.sorts.forEach(sort => {
38 | // 前端目前无法实现多字段排序,因此排序以最后一个字段为准
39 | sortArray(queryResult, sort.field, sort.value === 'desc')
40 | })
41 | return {
42 | code: 1,
43 | message: '操作成功',
44 | data: queryResult
45 | }
46 | },
47 | queryById: config => {
48 | console.log(config)
49 | const params = param2Obj(config.url)
50 | const dictionary = MockDB.dictionaries[MockDB.dictionaries.findIndex(item => { return item.id === params.id })]
51 | return {
52 | code: 1,
53 | message: '操作成功',
54 | data: dictionary
55 | }
56 | },
57 | add: config => {
58 | console.log(config)
59 | const params = JSON.parse(config.body)
60 | const dictionary = Mock.mock(MockDB.dictionaryMockConfig)
61 | params.id = dictionary.id
62 | deepMerge(dictionary, params)
63 | MockDB.dictionaries.push(dictionary)
64 | return {
65 | code: 1,
66 | message: '操作成功',
67 | data: {}
68 | }
69 | },
70 | edit: config => {
71 | console.log(config)
72 | const params = JSON.parse(config.body)
73 | const dictionary = MockDB.dictionaries[MockDB.dictionaries.findIndex(item => { return item.id === params.id })]
74 | deepMerge(dictionary, params)
75 | return {
76 | code: 1,
77 | message: '操作成功',
78 | data: {}
79 | }
80 | },
81 | del: config => {
82 | console.log(config)
83 | const params = JSON.parse(config.body)
84 | MockDB.dictionaries.splice(MockDB.dictionaries.findIndex(item => { return item.id === params.id }), 1)
85 | return {
86 | code: 1,
87 | message: '操作成功',
88 | data: {}
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/mock/system-management/menu.js:
--------------------------------------------------------------------------------
1 | import Mock from 'mockjs'
2 | import { deepMerge, param2Obj } from '@/utils'
3 | import { asyncMenuMap } from '@/router'
4 | import * as MockDB from '../MockDB'
5 |
6 | function createMenu(router, parentId, menus) {
7 | const menu = {}
8 | menu.id = router.name
9 | menu.parentId = parentId
10 | menu.deleted = 0
11 | menu.sortNum = router.meta.sortNum
12 | menu.name = router.meta.title
13 | menu.icon = router.meta.icon
14 | menu.remark = Mock.mock('@cparagraph(1, 3)')
15 | menu.createdBy = Mock.mock('@id')
16 | menu.createdDate = Mock.mock('@date(\'T\')')
17 | menu.modifiedBy = Mock.mock('@id')
18 | menu.modifiedDate = Mock.mock('@date(\'T\')')
19 |
20 | if (router.children && router.children.length > 0) {
21 | router.children.forEach(children => {
22 | createMenu(children, router.name, menus)
23 | })
24 | }
25 | menus.push(menu)
26 | }
27 |
28 | export default {
29 | queryAll: config => {
30 | console.log(config)
31 | return {
32 | code: 1,
33 | message: '操作成功',
34 | data: MockDB.menus
35 | }
36 | },
37 | queryById: config => {
38 | console.log(config)
39 | const params = param2Obj(config.url)
40 | const menu = MockDB.menus[MockDB.menus.findIndex(item => { return item.id === params.id })]
41 | return {
42 | code: 1,
43 | message: '操作成功',
44 | data: menu
45 | }
46 | },
47 | edit: config => {
48 | console.log(config)
49 | const params = JSON.parse(config.body)
50 | const menu = MockDB.menus[MockDB.menus.findIndex(item => { return item.id === params.id })]
51 | deepMerge(menu, params)
52 | return {
53 | code: 1,
54 | message: '操作成功',
55 | data: {}
56 | }
57 | },
58 |
59 | sync: config => {
60 | console.log(config)
61 | asyncMenuMap.forEach(router => createMenu(router, null, MockDB.menus))
62 | return {
63 | code: 1,
64 | message: '操作成功',
65 | data: {}
66 | }
67 | },
68 | queryAllMenuSecurities: config => {
69 | console.log(config)
70 | const params = param2Obj(config.url)
71 | const tempResult = MockDB.menuSecurities.filter(item => { return item.menuId === params.id })
72 | return {
73 | code: 1,
74 | message: '操作成功',
75 | data: MockDB.securities.filter(security => {
76 | return tempResult.findIndex(item => { return security.id === item.securityId }) !== -1
77 | })
78 | }
79 | },
80 | queryMenuRoles: config => {
81 | console.log(config)
82 | const params = param2Obj(config.url)
83 | if (MockDB.roleMenus.findIndex(item => { return item.menuId === params.id }) === -1) {
84 | // 生成几个role
85 | for (let i = 0; i < 5; i++) {
86 | const role = Mock.mock(MockDB.roleMockConfig)
87 | MockDB.roles.push(role)
88 | MockDB.roleMenus.push({
89 | menuId: params.id,
90 | roleId: role.id
91 | })
92 | }
93 | }
94 | const roleMenusResult = MockDB.roleMenus.filter(item => { return params.id === item.menuId })
95 | return {
96 | code: 1,
97 | message: '操作成功',
98 | data: MockDB.roles.filter(role => {
99 | return roleMenusResult.findIndex(menuRole => { return role.id === menuRole.roleId }) !== -1
100 | })
101 | }
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/mock/system-management/menuRole.js:
--------------------------------------------------------------------------------
1 | import * as MockDB from '../MockDB'
2 |
3 | export default {
4 | delByEntityMapping: config => {
5 | console.log(config)
6 | const params = JSON.parse(config.body)
7 | MockDB.roleMenus.splice(MockDB.roleMenus.findIndex(item => {
8 | return item.menuId === params.menuId && item.roleId === params.roleId
9 | }), 1)
10 | return {
11 | code: 1,
12 | message: '操作成功',
13 | data: {}
14 | }
15 | },
16 | reset: config => {
17 | console.log(config)
18 | const params = JSON.parse(config.body)
19 | MockDB.roleMenus.forEach(() => {
20 | MockDB.roleMenus.splice(MockDB.roleMenus.findIndex(item => {
21 | return item.roleId === params.roleId
22 | }), 1)
23 | })
24 | params.menuIds.forEach(menuId => {
25 | MockDB.roleMenus.push({
26 | roleId: params.roleId,
27 | menuId
28 | })
29 | })
30 | return {
31 | code: 1,
32 | message: '操作成功',
33 | data: ''
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/mock/system-management/menuSecurity.js:
--------------------------------------------------------------------------------
1 | import * as MockDB from '../MockDB'
2 |
3 | export default {
4 | add: config => {
5 | console.log(config)
6 | const params = JSON.parse(config.body)
7 | MockDB.menuSecurities.push(params)
8 | return {
9 | code: 1,
10 | message: '操作成功',
11 | data: params
12 | }
13 | },
14 | delByEntityMapping: config => {
15 | console.log(config)
16 | const params = JSON.parse(config.body)
17 | MockDB.menuSecurities.splice(MockDB.menuSecurities.findIndex(item => {
18 | return item.menuId === params.menuId && item.securityId === params.securityId
19 | }), 1)
20 | return {
21 | code: 1,
22 | message: '操作成功',
23 | data: ''
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/mock/system-management/roleGroup.js:
--------------------------------------------------------------------------------
1 | import * as MockDB from '../MockDB'
2 |
3 | export default {
4 | delByEntityMapping: config => {
5 | console.log(config)
6 | const params = JSON.parse(config.body)
7 | MockDB.roleGroups.splice(MockDB.roleGroups.findIndex(item => {
8 | return item.roleId === params.roleId && item.groupId === params.groupId
9 | }), 1)
10 | return {
11 | code: 1,
12 | message: '操作成功',
13 | data: ''
14 | }
15 | },
16 | add: config => {
17 | console.log(config)
18 | const params = JSON.parse(config.body)
19 | MockDB.roleGroups.push(params)
20 | return {
21 | code: 1,
22 | message: '操作成功',
23 | data: params
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/mock/system-management/security.js:
--------------------------------------------------------------------------------
1 | import Mock from 'mockjs'
2 | import { param2Obj, deepMerge, deepClone, fieldQueryLike, sortArray } from '@/utils'
3 | import * as MockDB from '../MockDB'
4 |
5 | export default {
6 | queryPage: config => {
7 | console.log(config)
8 | const params = JSON.parse(config.body)
9 | const query = {}
10 | params.filters.forEach(filter => {
11 | query[filter.field] = filter.value
12 | })
13 | const queryResult = deepClone(fieldQueryLike(MockDB.securities, query))
14 | params.sorts.forEach(sort => {
15 | // 前端目前无法实现多字段排序,因此排序以最后一个字段为准
16 | sortArray(queryResult, sort.field, sort.value === 'desc')
17 | })
18 | return {
19 | code: 1,
20 | message: '',
21 | data: {
22 | total: queryResult.length,
23 | pageSize: params.pageSize,
24 | page: params.page,
25 | list: queryResult.slice((params.page - 1) * params.pageSize, params.page * params.pageSize)
26 | }
27 | }
28 | },
29 | queryAll: config => {
30 | console.log(config)
31 | const params = JSON.parse(config.body)
32 | const query = {}
33 | params.filters.forEach(filter => {
34 | query[filter.field] = filter.value + ''
35 | })
36 | console.log(query)
37 | const queryResult = deepClone(fieldQueryLike(MockDB.securities, query))
38 | params.sorts.forEach(sort => {
39 | // 前端目前无法实现多字段排序,因此排序以最后一个字段为准
40 | sortArray(queryResult, sort.field, sort.value === 'desc')
41 | })
42 | return {
43 | code: 1,
44 | message: '操作成功',
45 | data: queryResult
46 | }
47 | },
48 | queryById: config => {
49 | console.log(config)
50 | const params = param2Obj(config.url)
51 | const security = MockDB.securities[MockDB.securities.findIndex(item => { return item.id === params.id })]
52 | return {
53 | code: 1,
54 | message: '操作成功',
55 | data: security
56 | }
57 | },
58 | add: config => {
59 | console.log(config)
60 | const params = JSON.parse(config.body)
61 | const security = Mock.mock(MockDB.securityMockConfig)
62 | params.id = security.id
63 | deepMerge(security, params)
64 | MockDB.securities.push(security)
65 | return {
66 | code: 1,
67 | message: '操作成功',
68 | data: security
69 | }
70 | },
71 | edit: config => {
72 | console.log(config)
73 | const params = JSON.parse(config.body)
74 | const security = MockDB.securities[MockDB.securities.findIndex(item => { return item.id === params.id })]
75 | deepMerge(security, params)
76 | return {
77 | code: 1,
78 | message: '操作成功',
79 | data: {}
80 | }
81 | },
82 | del: config => {
83 | console.log(config)
84 | const params = JSON.parse(config.body)
85 | MockDB.securities.splice(MockDB.securities.findIndex(item => { return item.id === params.id }), 1)
86 | return {
87 | code: 1,
88 | message: '操作成功',
89 | data: {}
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/mock/system-management/userDept.js:
--------------------------------------------------------------------------------
1 | import * as MockDB from '../MockDB'
2 |
3 | export default {
4 | delByEntityMapping: config => {
5 | console.log(config)
6 | const params = JSON.parse(config.body)
7 | MockDB.deptUsers.splice(MockDB.deptUsers.findIndex(item => {
8 | return item.userId === params.userId && item.deptId === params.deptId
9 | }), 1)
10 | return {
11 | code: 1,
12 | message: '操作成功',
13 | data: ''
14 | }
15 | },
16 | add: config => {
17 | console.log(config)
18 | const params = JSON.parse(config.body)
19 | MockDB.deptUsers.push(params)
20 | return {
21 | code: 1,
22 | message: '操作成功',
23 | data: params
24 | }
25 | },
26 | reset: config => {
27 | console.log(config)
28 | const params = JSON.parse(config.body)
29 | const newDeptUsers = MockDB.deptUsers.filter(item => {
30 | let found = false
31 | for (let i = 0; i < params.length; i++) {
32 | if (item.userId === params[i].userId) {
33 | found = true
34 | break
35 | }
36 | }
37 | return !found
38 | })
39 | MockDB.deptUsers.splice(0, MockDB.deptUsers.length)
40 | newDeptUsers.forEach(item => {
41 | MockDB.deptUsers.push(item)
42 | })
43 | params.forEach(item => {
44 | MockDB.deptUsers.push(item)
45 | })
46 | return {
47 | code: 1,
48 | message: '操作成功',
49 | data: params
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/mock/system-management/userGroup.js:
--------------------------------------------------------------------------------
1 | import * as MockDB from '../MockDB'
2 |
3 | export default {
4 | delByEntityMapping: config => {
5 | console.log(config)
6 | const params = JSON.parse(config.body)
7 | MockDB.userGroups.splice(MockDB.userGroups.findIndex(item => {
8 | return item.userId === params.userId && item.groupId === params.groupId
9 | }), 1)
10 | return {
11 | code: 1,
12 | message: '操作成功',
13 | data: ''
14 | }
15 | },
16 | add: config => {
17 | console.log(config)
18 | const params = JSON.parse(config.body)
19 | MockDB.userGroups.push(params)
20 | return {
21 | code: 1,
22 | message: '操作成功',
23 | data: params
24 | }
25 | },
26 | reset: config => {
27 | console.log(config)
28 | const params = JSON.parse(config.body)
29 | const newGroupUsers = MockDB.userGroups.filter(item => {
30 | let found = false
31 | for (let i = 0; i < params.length; i++) {
32 | if (item.userId === params[i].userId) {
33 | found = true
34 | break
35 | }
36 | }
37 | return !found
38 | })
39 | MockDB.userGroups.splice(0, MockDB.userGroups.length)
40 | newGroupUsers.forEach(item => {
41 | MockDB.userGroups.push(item)
42 | })
43 | params.forEach(item => {
44 | MockDB.userGroups.push(item)
45 | })
46 | return {
47 | code: 1,
48 | message: '操作成功',
49 | data: params
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/mock/system-management/userGroupRoleGroup.js:
--------------------------------------------------------------------------------
1 | import * as MockDB from '../MockDB'
2 |
3 | export default {
4 | delByEntityMapping: config => {
5 | console.log(config)
6 | const params = JSON.parse(config.body)
7 | MockDB.userGroupRoleGroups.splice(MockDB.userGroupRoleGroups.findIndex(item => {
8 | return item.userGroupId === params.userGroupId && item.roleGroupId === params.roleGroupId
9 | }), 1)
10 | return {
11 | code: 1,
12 | message: '操作成功',
13 | data: {}
14 | }
15 | },
16 | add: config => {
17 | console.log(config)
18 | const params = JSON.parse(config.body)
19 | MockDB.userGroupRoleGroups.push(params)
20 | return {
21 | code: 1,
22 | message: '操作成功',
23 | data: params
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/mock/system-management/userRole.js:
--------------------------------------------------------------------------------
1 | import * as MockDB from '../MockDB'
2 |
3 | export default {
4 | delByEntityMapping: config => {
5 | console.log(config)
6 | const params = JSON.parse(config.body)
7 | MockDB.userRoles.splice(MockDB.userRoles.findIndex(item => {
8 | return item.userId === params.userId && item.roleId === params.roleId
9 | }), 1)
10 | return {
11 | code: 1,
12 | message: '操作成功',
13 | data: ''
14 | }
15 | },
16 | add: config => {
17 | console.log(config)
18 | const params = JSON.parse(config.body)
19 | MockDB.userRoles.push(params)
20 | return {
21 | code: 1,
22 | message: '操作成功',
23 | data: params
24 | }
25 | },
26 | reset: config => {
27 | console.log(config)
28 | const params = JSON.parse(config.body)
29 | const newUserRoles = MockDB.userRoles.filter(item => {
30 | let found = false
31 | for (let i = 0; i < params.length; i++) {
32 | if (item.userId === params[i].userId) {
33 | found = true
34 | break
35 | }
36 | }
37 | return !found
38 | })
39 | MockDB.userRoles.splice(0, MockDB.userRoles.length)
40 | newUserRoles.forEach(item => {
41 | MockDB.userRoles.push(item)
42 | })
43 | params.forEach(item => {
44 | MockDB.userRoles.push(item)
45 | })
46 | return {
47 | code: 1,
48 | message: '操作成功',
49 | data: params
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/mock/system-management/userRoleGroup.js:
--------------------------------------------------------------------------------
1 | import * as MockDB from '../MockDB'
2 |
3 | export default {
4 | delByEntityMapping: config => {
5 | console.log(config)
6 | const params = JSON.parse(config.body)
7 | MockDB.userRoleGroups.splice(MockDB.userRoleGroups.findIndex(item => {
8 | return item.userId === params.userId && item.userRoleId === params.userRoleId
9 | }), 1)
10 | return {
11 | code: 1,
12 | message: '操作成功',
13 | data: {}
14 | }
15 | },
16 | add: config => {
17 | console.log(config)
18 | const params = JSON.parse(config.body)
19 | MockDB.userRoleGroups.push(params)
20 | return {
21 | code: 1,
22 | message: '操作成功',
23 | data: params
24 | }
25 | },
26 | reset: config => {
27 | console.log(config)
28 | const params = JSON.parse(config.body)
29 | const newUserRoleGroups = MockDB.userRoleGroups.filter(item => {
30 | let found = false
31 | for (let i = 0; i < params.length; i++) {
32 | if (item.userId === params[i].userId) {
33 | found = true
34 | break
35 | }
36 | }
37 | return !found
38 | })
39 | MockDB.userRoleGroups.splice(0, MockDB.userRoleGroups.length)
40 | newUserRoleGroups.forEach(item => {
41 | MockDB.userRoleGroups.push(item)
42 | })
43 | params.forEach(item => {
44 | MockDB.userRoleGroups.push(item)
45 | })
46 | return {
47 | code: 1,
48 | message: '操作成功',
49 | data: params
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/mock/utils.js:
--------------------------------------------------------------------------------
1 | import Mock from 'mockjs'
2 |
3 | const id = []
4 | for (let i = 0; i < 1000; i++) {
5 | id.push(Mock.mock('@id'))
6 | }
7 |
8 | export default {
9 | state: [0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1],
10 | deleted: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1],
11 | id: id
12 | }
13 |
--------------------------------------------------------------------------------
/src/permission.js:
--------------------------------------------------------------------------------
1 | import router from './router'
2 | import store from './store'
3 | import { Message } from 'element-ui'
4 | import NProgress from 'nprogress' // 进度条组件
5 | import 'nprogress/nprogress.css'// 进度条样式
6 | import { getToken, hasPermission } from '@/utils/auth' // 从cookie中获取用户信息
7 |
8 | NProgress.configure({ showSpinner: false })// NProgress Configuration
9 |
10 | router.beforeEach((to, from, next) => {
11 | NProgress.start() // 开始进度条
12 | if (getToken()) { // 判断是否已存在token信息
13 | if (to.path.indexOf('/login') === 0) {
14 | next({ path: '/' })
15 | NProgress.done() // 部分页面可能不会触发路由afterEach钩子
16 | } else {
17 | if (store.getters.user === null) { // 判断当前用户是否已拉取完用户信息
18 | store.dispatch('GetUserInfo').then(data => { // 拉取用户信息
19 | const roles = data.roles // 必须是数组结构
20 | store.dispatch('GenerateRoutes', { roles }).then(() => { // 根据roles权限生成可访问的路由表
21 | router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表
22 | next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
23 | })
24 | }).catch((err) => {
25 | store.dispatch('FedLogOut').then(() => {
26 | Message.error(err || '登录失败')
27 | next({ path: '/' })
28 | })
29 | })
30 | } else {
31 | // 没有动态改变权限的需求可直接next() 删除下方权限判断
32 | if (hasPermission(store.getters.roles, to)) {
33 | next()
34 | } else {
35 | next({ path: '/401', replace: true, query: { noGoBack: true }})
36 | }
37 | }
38 | }
39 | } else {
40 | if (to.path.indexOf('/login') === 0) {
41 | next()
42 | } else {
43 | next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页
44 | NProgress.done() // 防止当前页面与to相同,导致afterEach钩子未触发
45 | }
46 | }
47 | })
48 |
49 | router.afterEach(() => {
50 | NProgress.done() // finish progress bar
51 | })
52 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 |
4 | Vue.use(Router)
5 |
6 | /**
7 | * Layout,建议在一级路由中应用不同的布局
8 | */
9 | import defaultLayout from '@/views/layout/LeftAccordionSidebar/index'
10 |
11 | /* 模块化路由 */
12 | import systemManagementRouter from './modules/SystemManagement'
13 | import CodeGenerator from './modules/CodeGenerator'
14 |
15 | /**
16 | * 静态路由定义,无需权限的全局路由
17 | * @type {*[]}
18 | */
19 | export const constantRouterMap = [
20 | {
21 | path: '/redirect', // 通常用于刷新当前路由,可参见tagsView中的案例
22 | component: defaultLayout,
23 | hidden: true,
24 | children: [
25 | {
26 | path: '/redirect/:path*',
27 | component: () => import('@/components/Redirect/index')
28 | }
29 | ]
30 | },
31 | {
32 | path: '/login',
33 | component: () => import('@/views/login/index'),
34 | hidden: true
35 | },
36 | {
37 | path: '/404',
38 | component: () => import('@/components/ErrorPage/404'),
39 | hidden: true
40 | },
41 | {
42 | path: '/401',
43 | component: () => import('@/components/ErrorPage/401'),
44 | hidden: true
45 | },
46 | {
47 | path: '/myself',
48 | component: defaultLayout,
49 | hidden: true,
50 | meta: { title: '个人设置', icon: 'user' },
51 | children: [
52 | {
53 | path: 'modify',
54 | component: () => import('@/views/system-management/user/myself/modify'),
55 | name: 'myself-modify',
56 | meta: { title: '个人信息编辑', icon: 'user' }
57 | }
58 | ]
59 | },
60 | {
61 | path: '',
62 | component: defaultLayout,
63 | hidden: false,
64 | redirect: 'index',
65 | children: [
66 | {
67 | path: '/index',
68 | component: () => import('@/views/dashboard/index'),
69 | name: 'index',
70 | meta: { title: '首页', icon: 'index' }
71 | }
72 | ]
73 | }
74 | ]
75 |
76 | export default new Router({
77 | routes: constantRouterMap
78 | })
79 |
80 | /**
81 | * 聚合子模块路由对象,登陆后异步匹配路由结构,动态添加路由
82 | * 建议,该动态路由表由前端控制
83 | * asyncRouterMap动态够钱过程中,请在最后末尾处加上路由 : { path: '*', redirect: '/404', hidden: true },将未知路由归置到404页面, 详见src/store/modules/permission.js
84 | */
85 | export const asyncRouterMap = [
86 | systemManagementRouter,
87 | CodeGenerator
88 | ]
89 |
90 | export const asyncMenuMap = JSON.parse(JSON.stringify(asyncRouterMap))
91 |
--------------------------------------------------------------------------------
/src/router/modules/CodeGenerator.js:
--------------------------------------------------------------------------------
1 | import defaultLayout from '@/views/layout/LeftAccordionSidebar/index'
2 |
3 | const asyncRouter = {
4 | path: '/java-code-generator',
5 | component: defaultLayout,
6 | hidden: false,
7 | redirect: '/java-code-generator/execute',
8 | name: '923c7i98uc6khj109b8930ba20d907j3',
9 | meta: {
10 | sortNum: 1,
11 | roles: [],
12 | title: '插件',
13 | icon: 'utils'
14 | },
15 | children: [
16 | {
17 | path: 'execute',
18 | component: () => import('@/views/code-generator/main'),
19 | hidden: false,
20 | alwaysShow: true,
21 | name: '723c7698uc6ghj109b8970baf0d008j5',
22 | meta: {
23 | sortNum: 2,
24 | roles: [],
25 | title: '代码生成器',
26 | icon: 'java'
27 | }
28 | }
29 | ]
30 | }
31 |
32 | export default asyncRouter
33 |
--------------------------------------------------------------------------------
/src/store/getters.js:
--------------------------------------------------------------------------------
1 | const getters = {
2 | sidebar: state => state.app.sidebar,
3 |
4 | visitedViews: state => state.tagsView.visitedViews,
5 |
6 | token: state => state.user.token,
7 | user: state => state.user.user,
8 | roles: state => state.user.roles,
9 |
10 | adminCode: state => state.permission.adminCode,
11 | permission_routers: state => state.permission.routers,
12 | addRouters: state => state.permission.addRouters,
13 |
14 | dictionaries: state => state.dictionaries
15 | }
16 | export default getters
17 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | import app from './modules/app'
4 | import permission from './modules/permission'
5 | import tagsView from './modules/tagsView'
6 | import user from './modules/user'
7 | import dictionaries from './modules/dictionaries'
8 | import getters from './getters'
9 |
10 | Vue.use(Vuex)
11 |
12 | const store = new Vuex.Store({
13 | modules: {
14 | app,
15 | permission,
16 | tagsView,
17 | user,
18 | dictionaries
19 | },
20 | getters
21 | })
22 |
23 | export default store
24 |
--------------------------------------------------------------------------------
/src/store/modules/app.js:
--------------------------------------------------------------------------------
1 | import Cookies from 'js-cookie'
2 |
3 | const app = {
4 | state: {
5 | sidebar: {
6 | opened: !+Cookies.get('sidebarStatus'),
7 | withoutAnimation: false
8 | }
9 | },
10 | mutations: {
11 | TOGGLE_SIDEBAR: state => {
12 | if (state.sidebar.opened) {
13 | Cookies.set('sidebarStatus', 1)
14 | } else {
15 | Cookies.set('sidebarStatus', 0)
16 | }
17 | state.sidebar.opened = !state.sidebar.opened
18 | state.sidebar.withoutAnimation = false
19 | },
20 | CLOSE_SIDEBAR: (state, withoutAnimation) => {
21 | Cookies.set('sidebarStatus', 1)
22 | state.sidebar.opened = false
23 | state.sidebar.withoutAnimation = withoutAnimation
24 | },
25 | OPEN_SIDEBAR: (state, withoutAnimation) => {
26 | Cookies.set('sidebarStatus', 0)
27 | state.sidebar.opened = true
28 | state.sidebar.withoutAnimation = withoutAnimation
29 | }
30 | },
31 | actions: {
32 | toggleSideBar({ commit }) {
33 | commit('TOGGLE_SIDEBAR')
34 | },
35 | closeSideBar({ commit }, { withoutAnimation }) {
36 | commit('CLOSE_SIDEBAR', withoutAnimation)
37 | },
38 | openSideBar({ commit }, { withoutAnimation }) {
39 | commit('OPEN_SIDEBAR', withoutAnimation)
40 | }
41 | }
42 | }
43 |
44 | export default app
45 |
--------------------------------------------------------------------------------
/src/store/modules/dictionaries.js:
--------------------------------------------------------------------------------
1 | const dictionaries = {
2 | state: {
3 | trueOrFalse: [{
4 | key: '0',
5 | value: '否'
6 | }, {
7 | key: '1',
8 | value: '是'
9 | }],
10 |
11 | gender: [{
12 | key: '0',
13 | value: '女'
14 | }, {
15 | key: '1',
16 | value: '男'
17 | }],
18 |
19 | dictionaryCategory: [{
20 | key: '1',
21 | value: '字典分类'
22 | }, {
23 | key: '2',
24 | value: '单级字典'
25 | }, {
26 | key: '3',
27 | value: '多级字典'
28 | }]
29 | }
30 | }
31 | export default dictionaries
32 |
--------------------------------------------------------------------------------
/src/store/modules/permission.js:
--------------------------------------------------------------------------------
1 | import { asyncRouterMap, constantRouterMap } from '@/router'
2 | import { filterAsyncRouter, initRouterRoles, initRouterRedirect } from '@/utils/auth'
3 | import { getRouterRoles } from '@/api/login'
4 |
5 | const permission = {
6 | state: {
7 | adminCode: 'admin',
8 | routers: constantRouterMap,
9 | addRouters: []
10 | },
11 | mutations: {
12 | SET_ROUTERS: (state, routers) => {
13 | state.routers = constantRouterMap.concat(routers)
14 | state.addRouters = routers
15 | }
16 | },
17 | actions: {
18 | GenerateRoutes({ commit, state }, data) {
19 | return new Promise(resolve => {
20 | const { roles } = data
21 | let accessedRouters = null
22 | if (roles.includes(state.adminCode)) {
23 | // 将未知路由归置到404页面
24 | asyncRouterMap.push({ path: '*', redirect: '/404', hidden: true })
25 | accessedRouters = asyncRouterMap
26 | initRouterRedirect(accessedRouters)
27 | commit('SET_ROUTERS', accessedRouters)
28 | resolve()
29 | } else {
30 | getRouterRoles().then(routerRoles => {
31 | const routerRolesMap = new Map(routerRoles)
32 | asyncRouterMap.forEach(module => {
33 | initRouterRoles(module, routerRolesMap)
34 | })
35 | accessedRouters = filterAsyncRouter(asyncRouterMap, roles)
36 | // 将未知路由归置到404页面
37 | accessedRouters.push({ path: '*', redirect: '/404', hidden: true })
38 | initRouterRedirect(accessedRouters)
39 | commit('SET_ROUTERS', accessedRouters)
40 | resolve()
41 | })
42 | }
43 | })
44 | }
45 | }
46 | }
47 |
48 | export default permission
49 |
--------------------------------------------------------------------------------
/src/store/modules/tagsView.js:
--------------------------------------------------------------------------------
1 | const tagsView = {
2 | state: {
3 | visitedViews: []
4 | },
5 | mutations: {
6 | ADD_VISITED_VIEW: (state, view) => {
7 | if (state.visitedViews.some(v => v.path === view.path)) return
8 | state.visitedViews.push(
9 | Object.assign({}, view, {
10 | title: view.meta.title || 'no-name'
11 | })
12 | )
13 | },
14 | DEL_VISITED_VIEW: (state, view) => {
15 | for (const [i, v] of state.visitedViews.entries()) {
16 | if (v.path === view.path) {
17 | state.visitedViews.splice(i, 1)
18 | break
19 | }
20 | }
21 | },
22 | DEL_OTHERS_VISITED_VIEWS: (state, view) => {
23 | for (const [i, v] of state.visitedViews.entries()) {
24 | if (v.path === view.path) {
25 | state.visitedViews = state.visitedViews.slice(i, i + 1)
26 | break
27 | }
28 | }
29 | },
30 | DEL_ALL_VISITED_VIEWS: state => {
31 | state.visitedViews = []
32 | },
33 | UPDATE_VISITED_VIEW: (state, view) => {
34 | for (let v of state.visitedViews) {
35 | if (v.path === view.path) {
36 | v = Object.assign(v, view)
37 | break
38 | }
39 | }
40 | }
41 |
42 | },
43 | actions: {
44 | addView({ dispatch }, view) {
45 | dispatch('addVisitedView', view)
46 | },
47 | addVisitedView({ commit }, view) {
48 | commit('ADD_VISITED_VIEW', view)
49 | },
50 | delView({ dispatch, state }, view) {
51 | return new Promise(resolve => {
52 | dispatch('delVisitedView', view)
53 | resolve({
54 | visitedViews: [...state.visitedViews]
55 | })
56 | })
57 | },
58 | delVisitedView({ commit, state }, view) {
59 | return new Promise(resolve => {
60 | commit('DEL_VISITED_VIEW', view)
61 | resolve([...state.visitedViews])
62 | })
63 | },
64 | delOthersViews({ dispatch, state }, view) {
65 | return new Promise(resolve => {
66 | dispatch('delOthersVisitedViews', view)
67 | resolve({
68 | visitedViews: [...state.visitedViews]
69 | })
70 | })
71 | },
72 | delOthersVisitedViews({ commit, state }, view) {
73 | return new Promise(resolve => {
74 | commit('DEL_OTHERS_VISITED_VIEWS', view)
75 | resolve([...state.visitedViews])
76 | })
77 | },
78 | delAllViews({ dispatch, state }, view) {
79 | return new Promise(resolve => {
80 | dispatch('delAllVisitedViews', view)
81 | resolve({
82 | visitedViews: [...state.visitedViews]
83 | })
84 | })
85 | },
86 | delAllVisitedViews({ commit, state }) {
87 | return new Promise(resolve => {
88 | commit('DEL_ALL_VISITED_VIEWS')
89 | resolve([...state.visitedViews])
90 | })
91 | },
92 | updateVisitedView({ commit }, view) {
93 | commit('UPDATE_VISITED_VIEW', view)
94 | }
95 | }
96 | }
97 |
98 | export default tagsView
99 |
--------------------------------------------------------------------------------
/src/store/modules/user.js:
--------------------------------------------------------------------------------
1 | import { logout, getUserInfo } from '@/api/login'
2 | import { getToken, setToken, removeToken } from '@/utils/auth'
3 |
4 | const user = {
5 | state: {
6 | token: getToken(),
7 | user: null,
8 | roles: []
9 | },
10 |
11 | mutations: {
12 | SET_TOKEN: (state, token) => {
13 | state.token = token
14 | if (token) {
15 | setToken(token)
16 | } else {
17 | removeToken()
18 | }
19 | },
20 | SET_USER: (state, user) => {
21 | state.user = user
22 | },
23 | SET_ROLES: (state, roles) => {
24 | state.roles = roles
25 | },
26 | CLEAR_USER: (state) => {
27 | state.user = null
28 | state.roles = []
29 | }
30 | },
31 |
32 | actions: {
33 | // 用户名登录
34 | LoginByLoginName({ commit }, token) {
35 | commit('SET_TOKEN', token)
36 | commit('CLEAR_USER')
37 | },
38 |
39 | // 获取用户信息
40 | GetUserInfo({ commit, state }) {
41 | return new Promise((resolve, reject) => {
42 | getUserInfo(state.token).then(data => {
43 | commit('SET_USER', data.user)
44 | commit('SET_ROLES', data.roles)
45 | resolve(data)
46 | }).catch(error => {
47 | commit('CLEAR_USER')
48 | reject(error)
49 | })
50 | })
51 | },
52 |
53 | // 登出
54 | LogOut({ commit, state }) {
55 | return new Promise((resolve, reject) => {
56 | logout(state.token).then(() => {
57 | commit('SET_TOKEN', null)
58 | commit('CLEAR_USER')
59 | resolve()
60 | }).catch(error => {
61 | reject(error)
62 | })
63 | })
64 | },
65 |
66 | // 前端 登出
67 | FedLogOut({ commit }) {
68 | return new Promise(resolve => {
69 | commit('SET_TOKEN', null)
70 | commit('CLEAR_USER')
71 | resolve()
72 | })
73 | }
74 | }
75 | }
76 |
77 | export default user
78 |
--------------------------------------------------------------------------------
/src/styles/element-ui.scss:
--------------------------------------------------------------------------------
1 | //覆盖一些element-ui样式
2 |
3 | .el-breadcrumb__inner, .el-breadcrumb__inner a {
4 | font-weight: 400!important;
5 | }
6 |
7 | .current-row {
8 | td {
9 | background-color: #409EFF !important;
10 | color: #f5f7fa;
11 | font-weight: 600;
12 | font-size: 16px;
13 | }
14 | }
15 |
16 | .el-upload {
17 | input[type="file"] {
18 | display: none !important;
19 | }
20 | }
21 |
22 | .el-upload__input {
23 | display: none;
24 | }
25 |
26 | //element ui upload
27 | .upload-container {
28 | .el-upload {
29 | width: 100%;
30 | .el-upload-dragger {
31 | width: 100%;
32 | height: 200px;
33 | }
34 | }
35 | }
36 |
37 | //dropdown
38 | .el-dropdown-menu{
39 | a {
40 | display: block
41 | }
42 | }
43 | .el-menu--vertical > .el-menu .svg-icon {
44 | margin-right: 20px;
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/src/styles/index.scss:
--------------------------------------------------------------------------------
1 | @import './mixin.scss';
2 | @import './transition.scss';
3 | @import './element-ui.scss';
4 |
5 | body {
6 | height: 100%;
7 | -moz-osx-font-smoothing: grayscale;
8 | -webkit-font-smoothing: antialiased;
9 | text-rendering: optimizeLegibility;
10 | font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
11 | }
12 |
13 | label {
14 | font-weight: 700;
15 | }
16 |
17 | html {
18 | height: 100%;
19 | box-sizing: border-box;
20 | }
21 |
22 | #app {
23 | height: 100%;
24 | }
25 |
26 | *, *:before, *:after {
27 | box-sizing: inherit;
28 | }
29 |
30 | a:focus, a:active {
31 | outline: none;
32 | }
33 |
34 | a, a:focus, a:hover {
35 | cursor: pointer;
36 | color: inherit;
37 | text-decoration: none;
38 | }
39 |
40 | div:focus{
41 | outline: none;
42 | }
43 |
44 | .block {
45 | display: block;
46 | }
47 |
48 | .pointer {
49 | cursor: pointer;
50 | }
51 |
--------------------------------------------------------------------------------
/src/styles/mixin.scss:
--------------------------------------------------------------------------------
1 | @mixin clearfix {
2 | &:after {
3 | content: "";
4 | display: table;
5 | clear: both;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/styles/transition.scss:
--------------------------------------------------------------------------------
1 | //globl transition css
2 |
3 | /*fade*/
4 | .fade-enter-active, .fade-leave-active {
5 | transition: opacity 0.28s;
6 | }
7 |
8 | .fade-enter, .fade-leave-active {
9 | opacity: 0;
10 | }
11 |
12 | /*fade-transform*/
13 | .fade-transform-leave-active, .fade-transform-enter-active {
14 | transition: all .5s;
15 | }
16 | .fade-transform-enter {
17 | opacity: 0;
18 | transform: translateX(-30px);
19 | }
20 | .fade-transform-leave-to {
21 | opacity: 0;
22 | transform: translateX(30px);
23 | }
24 |
--------------------------------------------------------------------------------
/src/utils/auth.js:
--------------------------------------------------------------------------------
1 | import Cookies from 'js-cookie'
2 |
3 | const TokenKey = 'USER_TOKEN'
4 |
5 | export function getToken() {
6 | return Cookies.get(TokenKey)
7 | }
8 |
9 | export function setToken(token) {
10 | return Cookies.set(TokenKey, token)
11 | }
12 |
13 | export function removeToken() {
14 | return Cookies.remove(TokenKey)
15 | }
16 |
17 | /**
18 | * 通过meta.role判断是否与当前用户权限匹配
19 | * @param roles 用户的角色列表
20 | * @param meta meta中规定了有权限操作的所有角色,只要用户具有其中一个即可
21 | */
22 | export function hasPermission(roles, { meta }) {
23 | if (roles.indexOf('admin') >= 0) return true
24 | if (meta && meta.roles) {
25 | return roles.some(role => meta.roles.includes(role))
26 | } else {
27 | return true
28 | }
29 | }
30 |
31 | /**
32 | * 递归过滤异步路由表,返回符合用户角色权限的路由表
33 | * @param routes asyncRouterMap
34 | * @param roles
35 | */
36 | export function filterAsyncRouter(routes, roles) {
37 | const res = []
38 |
39 | routes.forEach(router => {
40 | const temp = { ...router } // 继承一个router对象,非深度复制
41 | if (hasPermission(roles, temp)) {
42 | if (temp.children) {
43 | temp.children = filterAsyncRouter(temp.children, roles)
44 | }
45 | res.push(temp)
46 | }
47 | })
48 |
49 | return res
50 | }
51 |
52 | export function initRouterRedirect(routes, redirect = '') {
53 | routes.forEach(router => {
54 | let routerRedirect = router.path
55 | // 约束,路由中请勿使用绝对路由路径path
56 | if (!router.path.startsWith('/')) {
57 | routerRedirect = redirect + '/' + router.path
58 | }
59 | if (router.children) {
60 | for (let i = 0; i < router.children.length; i++) {
61 | if (router.children[i].hidden === false) {
62 | router.redirect = routerRedirect + '/' + router.children[i].path
63 | break
64 | }
65 | }
66 | initRouterRedirect(router.children, routerRedirect)
67 | }
68 | })
69 | }
70 |
71 | export function initRouterRoles(router, routerRolesMap) {
72 | if (!router.meta) {
73 | router.meta = { }
74 | }
75 | if (routerRolesMap.get(router.name)) {
76 | router.meta.roles = routerRolesMap.get(router.name)
77 | } else {
78 | router.meta.roles = []
79 | }
80 | if (router.children) {
81 | router.children.forEach(children => {
82 | initRouterRoles(children, routerRolesMap)
83 | })
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/utils/clipboard.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Clipboard from 'clipboard'
3 |
4 | function clipboardSuccess() {
5 | Vue.prototype.$message({
6 | message: 'Copy successfully',
7 | type: 'success',
8 | duration: 1500
9 | })
10 | }
11 |
12 | function clipboardError() {
13 | Vue.prototype.$message({
14 | message: 'Copy failed',
15 | type: 'error'
16 | })
17 | }
18 |
19 | export default function handleClipboard(text, event) {
20 | const clipboard = new Clipboard(event.target, {
21 | text: () => text
22 | })
23 | clipboard.on('success', () => {
24 | clipboardSuccess()
25 | clipboard.off('error')
26 | clipboard.off('success')
27 | clipboard.destroy()
28 | })
29 | clipboard.on('error', () => {
30 | clipboardError()
31 | clipboard.off('error')
32 | clipboard.off('success')
33 | clipboard.destroy()
34 | })
35 | clipboard.onClick(event)
36 | }
37 |
--------------------------------------------------------------------------------
/src/utils/openWindow.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 打开windows窗口
3 | * @param {Sting} url
4 | * @param {Sting} title
5 | * @param {Number} w
6 | * @param {Number} h
7 | */
8 |
9 | export default function openWindow(url, title, w, h) {
10 | // Fixes dual-screen position Most browsers Firefox
11 | const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left
12 | const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top
13 |
14 | const width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width
15 | const height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height
16 |
17 | const left = ((width / 2) - (w / 2)) + dualScreenLeft
18 | const top = ((height / 2) - (h / 2)) + dualScreenTop
19 | const newWindow = window.open(url, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=yes, copyhistory=no, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left)
20 |
21 | // Puts focus on the newWindow
22 | if (window.focus) {
23 | newWindow.focus()
24 | }
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/src/utils/permission.js:
--------------------------------------------------------------------------------
1 | import store from '@/store'
2 |
3 | /**
4 | * @param {Array} value
5 | * @returns {Boolean}
6 | * @example see @/views/permission/directive.vue
7 | */
8 | export default function checkPermission(value) {
9 | if (value && value instanceof Array && value.length > 0) {
10 | const roles = store.getters && store.getters.roles
11 | const permissionRoles = value
12 |
13 | const hasPermission = roles.some(role => {
14 | return permissionRoles.includes(role)
15 | })
16 |
17 | if (!hasPermission) {
18 | return false
19 | }
20 | return true
21 | } else {
22 | console.error('权限不足')
23 | return false
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/utils/request.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import Qs from 'Qs'
3 | import { Message } from 'element-ui'
4 | import store from '@/store'
5 |
6 | // 本工程中axios使用,均通过其API构建请求,可参考https://www.kancloud.cn/yunye/axios/234845
7 | // create an axios instance
8 | const service = axios.create({
9 | baseURL: process.env.BASE_API, // api 的 base_url
10 | timeout: 20000 // request timeout
11 | })
12 | service.defaults.withCredentials = true
13 |
14 | // request interceptor
15 | service.interceptors.request.use(
16 | request => {
17 | // 后端服务jwt token信息
18 | if (store.getters.token) {
19 | request.headers.common['Authorization'] = `${store.getters.token}`
20 | }
21 | return request
22 | },
23 | error => {
24 | // 请求发生错误
25 | console.log('request interceptor error') // for debug
26 | Promise.reject(error)
27 | }
28 | )
29 | // {
30 | // code: 1, //1:正确结果,2:回话过期,3:非法回话,4:权限不足,5:未知错误
31 | // message: 后端错误信息
32 | // data: 后端正常处理结果封装
33 | // }
34 | // response interceptor
35 | service.interceptors.response.use(
36 | response => {
37 | const res = response.data
38 | if ('' + res.code !== '1') {
39 | if (('' + res.code).indexOf('3') === 0) { // 规则码3开头的均为回话问题,token过期等
40 | Message({
41 | message: '你已从其他终端登出,或回话已超时,请重新登录',
42 | type: 'warning'
43 | })
44 | store.dispatch('FedLogOut').then(() => {
45 | location.reload() // 为了重新实例化vue-router对象 避免bug
46 | })
47 | }
48 | console.log('response interceptor: error') // for debug
49 | if (res.message) {
50 | Message({
51 | message: res.message,
52 | type: 'error',
53 | duration: 3 * 1000
54 | })
55 | }
56 | return Promise.reject('error')
57 | } else {
58 | console.log(res.data)
59 | return res.data
60 | }
61 | },
62 | error => {
63 | console.log('response interceptor error') // for debug
64 | Message({
65 | message: error.message,
66 | type: 'error',
67 | duration: 3 * 1000
68 | })
69 | return Promise.reject(error)
70 | }
71 | )
72 |
73 | export default function ({ url, method = 'get', data = null }) {
74 | // 解决axios post请求Request Payload问题
75 | if (data && method.toLowerCase() === 'post') {
76 | // 对 data 进行任意转换处理
77 | const isDeep = Object.keys(data).findIndex(prop => {
78 | const type = Object.prototype.toString.call(data[prop])
79 | return type === '[object Object]' || type === '[object Array]' || type === '[object JSON]'
80 | }) !== -1
81 |
82 | if (isDeep) {
83 | // 嵌套data,对层JSON对象,提交时采用 Request Payload 方案
84 | // data 原样输出
85 | } else {
86 | // 非嵌套data,提交时采用Request FormData方案
87 | // data需要进行转换
88 | data = Qs.stringify(data)
89 | }
90 | }
91 | if (method.toLowerCase() === 'post') {
92 | return service({
93 | url,
94 | method,
95 | data
96 | })
97 | } else if(method.toLowerCase() === 'get') {
98 | return service({
99 | url,
100 | method,
101 | params: data
102 | })
103 | } else {
104 | throw "目前仅仅支持get/post方法"
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/utils/scrollTo.js:
--------------------------------------------------------------------------------
1 | Math.easeInOutQuad = function(t, b, c, d) {
2 | t /= d / 2
3 | if (t < 1) {
4 | return c / 2 * t * t + b
5 | }
6 | t--
7 | return -c / 2 * (t * (t - 2) - 1) + b
8 | }
9 |
10 | // requestAnimationFrame for Smart Animating http://goo.gl/sx5sts
11 | var requestAnimFrame = (function() {
12 | return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60) }
13 | })()
14 |
15 | // because it's so fucking difficult to detect the scrolling element, just move them all
16 | function move(amount) {
17 | document.documentElement.scrollTop = amount
18 | document.body.parentNode.scrollTop = amount
19 | document.body.scrollTop = amount
20 | }
21 |
22 | function position() {
23 | return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop
24 | }
25 |
26 | export function scrollTo(to, duration, callback) {
27 | const start = position()
28 | const change = to - start
29 | const increment = 20
30 | let currentTime = 0
31 | duration = (typeof (duration) === 'undefined') ? 500 : duration
32 | var animateScroll = function() {
33 | // increment the time
34 | currentTime += increment
35 | // find the value with the quadratic in-out easing function
36 | var val = Math.easeInOutQuad(currentTime, start, change, duration)
37 | // move the document.body
38 | move(val)
39 | // do the animation unless its over
40 | if (currentTime < duration) {
41 | requestAnimFrame(animateScroll)
42 | } else {
43 | if (callback && typeof (callback) === 'function') {
44 | // the animation is done so lets callback
45 | callback()
46 | }
47 | }
48 | }
49 | animateScroll()
50 | }
51 |
--------------------------------------------------------------------------------
/src/utils/validate.js:
--------------------------------------------------------------------------------
1 |
2 | /* 合法uri*/
3 | export function validateURL(textval) {
4 | const urlregex = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
5 | return urlregex.test(textval)
6 | }
7 |
8 | /* 小写字母*/
9 | export function validateLowerCase(str) {
10 | const reg = /^[a-z]+$/
11 | return reg.test(str)
12 | }
13 |
14 | /* 大写字母*/
15 | export function validateUpperCase(str) {
16 | const reg = /^[A-Z]+$/
17 | return reg.test(str)
18 | }
19 |
20 | /* 大小写字母*/
21 | export function validateAlphabets(str) {
22 | const reg = /^[A-Za-z]+$/
23 | return reg.test(str)
24 | }
25 |
26 | /**
27 | * validate email
28 | * @param email
29 | * @returns {boolean}
30 | */
31 | export function validateEmail(email) {
32 | const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
33 | return re.test(email)
34 | }
35 |
--------------------------------------------------------------------------------
/src/views/code-generator/main.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | dd
5 |
6 |
7 |
8 |
9 |
22 |
--------------------------------------------------------------------------------
/src/views/common/components/auditInfo/auditInfo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ detail.createdBy }}
4 | {{ detail.createdDate | parseTime }}
5 | {{ detail.modifiedBy }}
6 | {{ detail.modifiedDate | parseTime }}
7 |
8 |
9 |
10 |
37 |
38 |
41 |
--------------------------------------------------------------------------------
/src/views/common/components/buttons/ButtonRight.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
34 |
--------------------------------------------------------------------------------
/src/views/common/components/buttons/NewLineButtonRight.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
25 |
--------------------------------------------------------------------------------
/src/views/common/components/dictionaryTranslates/State.vue:
--------------------------------------------------------------------------------
1 |
2 | {{ state | translateTrueOrFalse }}
3 |
4 |
5 |
16 |
--------------------------------------------------------------------------------
/src/views/common/components/formItemViews/InputItemView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
13 |
14 |
42 |
43 |
54 |
--------------------------------------------------------------------------------
/src/views/common/components/formItemViews/TextItemView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
13 |
14 |
42 |
43 |
54 |
--------------------------------------------------------------------------------
/src/views/common/components/layouts/FlexCenter.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
16 |
--------------------------------------------------------------------------------
/src/views/common/components/layouts/FlexLeft.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
16 |
--------------------------------------------------------------------------------
/src/views/common/components/layouts/FlexRight.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
16 |
--------------------------------------------------------------------------------
/src/views/common/components/paginations/pagination.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
46 |
47 |
52 |
--------------------------------------------------------------------------------
/src/views/common/components/selects/SelectRight.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
17 |
18 |
40 |
--------------------------------------------------------------------------------
/src/views/common/index.js:
--------------------------------------------------------------------------------
1 | import upperFirst from 'lodash/upperFirst'
2 | import camelCase from 'lodash/camelCase'
3 |
4 | const requireComponent = require.context(
5 | // 其组件目录的相对路径
6 | './components',
7 | // 是否查询其子目录
8 | true,
9 | // 匹配基础组件文件名的正则表达式
10 | /[A-Za-z]\w+\.vue$/
11 | )
12 |
13 | const components = {}
14 |
15 | requireComponent.keys().forEach(fileName => {
16 | // 获取组件配置
17 | const componentConfig = requireComponent(fileName)
18 |
19 | fileName = (fileName.split('/'))[fileName.split('/').length - 1]
20 |
21 | // 获取组件的 PascalCase 命名
22 | const componentName = upperFirst(
23 | camelCase(
24 | // 排出子目录
25 | // 结尾的扩展名
26 | fileName.replace('.vue', '')
27 | )
28 | )
29 |
30 | // 如果这个组件选项是通过 `export default` 导出的,
31 | // 那么就会优先使用 `.default`,
32 | // 否则回退到使用模块的根。
33 | components[componentName] = componentConfig.default || componentConfig
34 | })
35 |
36 | export default components
37 |
--------------------------------------------------------------------------------
/src/views/common/mixins/BaseEditForm.js:
--------------------------------------------------------------------------------
1 | /**
2 | * newest 记录最新的表单(通常为后端返回结果存储)
3 | */
4 | export default {
5 | methods: {
6 | backHandler(data) {
7 | if (this.customBackHandler) {
8 | this.customBackHandler(data)
9 | } else {
10 | this.$emit('option-changed')
11 | }
12 | },
13 | submitHandler(form, otherSubmitHandler = null) {
14 | this.newest = null
15 | this.$refs[form].validate((valid) => {
16 | if (!valid) return false
17 | this.$confirm('确定要保存吗?', '提示', {
18 | confirmButtonText: '确定',
19 | cancelButtonText: '取消',
20 | type: 'warning'
21 | }).then(() => {
22 | if (otherSubmitHandler) {
23 | otherSubmitHandler()
24 | } else {
25 | this.customSubmitHandler()
26 | }
27 | }).catch(() => {
28 | this.$message({
29 | type: 'info',
30 | message: '已取消操作'
31 | })
32 | })
33 | })
34 | },
35 | submitSuccessHandler(data) {
36 | this.optionSuccessHandler()
37 | this.newest = data
38 | if (this.customSubmitSuccessHandler) {
39 | this.customSubmitSuccessHandler(data)
40 | } else {
41 | this.backHandler(data)
42 | }
43 | },
44 | optionSuccessHandler() {
45 | this.$message({
46 | type: 'success',
47 | message: '操作成功'
48 | })
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/views/common/mixins/BaseQueryPageForm.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 适用于一个一个查询对象+一个分页结果集展示的简单组件
3 | * 约束:
4 | * 寄主对象中应具有:
5 | * --this.queryCriteria : 表单查询对象封装
6 | * --this.initQueryCriteria() : 表单查询对象初始化函数
7 | * --this.executeQueryPage : 分页表单查询接口
8 | */
9 |
10 | import { deepMerge, deepClone } from '@/utils'
11 |
12 | export default {
13 | data() {
14 | const pagination = this.initPagination()
15 | return {
16 | autoRefresh: true,
17 | pagination: pagination
18 | }
19 | },
20 | activated() {
21 | if (this.autoRefresh) {
22 | this.executeQueryPage()
23 | }
24 | },
25 | methods: {
26 | initPagination(pagination = {}) {
27 | return deepMerge(pagination, {
28 | total: 0,
29 | pageSize: 10,
30 | page: 1,
31 | list: [],
32 | filters: [],
33 | sorts: []
34 | })
35 | },
36 | resetHandler() {
37 | this.initQueryCriteria(this.queryCriteria)
38 | this.initPagination(this.pagination)
39 | this.executeQueryPage()
40 | },
41 | queryHandler() {
42 | this.initPagination(this.pagination)
43 | this.executeQueryPage()
44 | },
45 | createQueryParams() {
46 | this.pagination.filters = []
47 | Object.keys(this.queryCriteria).forEach(key => {
48 | const value = this.queryCriteria[key]
49 | if (value) {
50 | if (typeof value === 'object') {
51 | this.pagination.filters.push({ field: key, value: deepClone(value) })
52 | } else {
53 | this.pagination.filters.push({ field: key, value: value })
54 | }
55 | }
56 | })
57 | let filters = this.pagination.filters;
58 | if (this.pagination.sorts) {
59 | filters = filters.concat(this.pagination.sorts)
60 | }
61 | console.log(filters)
62 | return {
63 | page: this.pagination.page,
64 | pageSize: this.pagination.pageSize,
65 | filters: filters
66 | }
67 | },
68 | queryResultHandler(result) {
69 | return deepMerge(this.pagination, result)
70 | },
71 | pageSizeChangeHandler(pageSize) {
72 | this.pagination.pageSize = pageSize
73 | this.pagination.page = 1
74 | this.executeQueryPage()
75 | },
76 | pageChangeHandler(page) {
77 | this.pagination.page = page
78 | this.executeQueryPage()
79 | },
80 | sortChangeHandler({ column, prop, order }) {
81 | // ElementUI 目前并不支持远端多字段排序
82 | // sorts数组设计的目的是为了支持ElementUI后续拓展
83 |
84 | this.pagination.sorts = []
85 | // sorts = [type: 'ORDER_BY_DESC', field: ['name']]
86 | if (column) {
87 | this.pagination.sorts.push({
88 | field: [prop],
89 | type: order === 'descending' ? 'ORDER_BY_DESC' : 'ORDER_BY_ASC'
90 | })
91 | }
92 | this.pagination.page = 1
93 | this.executeQueryPage()
94 | },
95 | delHandler() {
96 | this.$confirm('此操作将永久删除, 是否继续?', '提示', {
97 | confirmButtonText: '确定',
98 | cancelButtonText: '取消',
99 | type: 'warning'
100 | }).then(() => {
101 | if (this.customDelHandler) {
102 | this.customDelHandler()
103 | } else {
104 | this.$message({
105 | type: 'info',
106 | message: '您未定义删除逻辑处理方法customDelHandler'
107 | })
108 | }
109 | }).catch(() => {
110 | this.$message({
111 | type: 'info',
112 | message: '已取消删除'
113 | })
114 | })
115 | }
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/src/views/dashboard/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
23 |
--------------------------------------------------------------------------------
/src/views/layout/LeftAccordionSidebar/components/AppMain.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
21 |
22 |
31 |
32 |
--------------------------------------------------------------------------------
/src/views/layout/LeftAccordionSidebar/components/Sidebar/Item.vue:
--------------------------------------------------------------------------------
1 |
30 |
--------------------------------------------------------------------------------
/src/views/layout/LeftAccordionSidebar/components/Sidebar/Link.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
39 |
--------------------------------------------------------------------------------
/src/views/layout/LeftAccordionSidebar/components/Sidebar/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 | UMI-SOFT
12 |
13 |
14 |
15 |
16 |
17 |
45 |
54 |
--------------------------------------------------------------------------------
/src/views/layout/LeftAccordionSidebar/components/index.js:
--------------------------------------------------------------------------------
1 | export { default as Navbar } from './Navbar'
2 | export { default as Sidebar } from './Sidebar/index.vue'
3 | export { default as TagsView } from './TagsView'
4 | export { default as AppMain } from './AppMain'
5 |
--------------------------------------------------------------------------------
/src/views/layout/LeftAccordionSidebar/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
39 |
40 |
133 |
--------------------------------------------------------------------------------
/src/views/layout/MenuGroup/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
15 |
16 |
19 |
--------------------------------------------------------------------------------
/src/views/system-management/dept/add.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | 保存
20 | 取消
21 |
22 |
23 |
24 |
25 |
70 |
71 |
74 |
--------------------------------------------------------------------------------
/src/views/system-management/dept/check.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
返回
4 |
5 |
6 |
7 | {{ detail.id }}
8 | {{ parentDeptName }}
9 | {{ detail.sortNum }}
10 | {{ detail.type }}
11 | {{ detail.name }}
12 | {{ detail.remark }}
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | {{ scope.row.gender | translateGender }}
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
65 |
66 |
71 |
--------------------------------------------------------------------------------
/src/views/system-management/dept/main.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
34 |
--------------------------------------------------------------------------------
/src/views/system-management/dept/mixins.js:
--------------------------------------------------------------------------------
1 | import * as DeptAPI from '@/api/system-management/dept'
2 |
3 | export default {
4 | data() {
5 | return {
6 | parentDeptName: '',
7 | users: [],
8 | roles: []
9 | }
10 | },
11 | methods: {
12 | initForm() {
13 | return {
14 | id: null,
15 | token: null,
16 | parentId: null,
17 | type: '',
18 | name: '',
19 | sortNum: '',
20 | remark: ''
21 | }
22 | },
23 | initRules() {
24 | return {
25 | type: [{
26 | required: true, message: '请输入部门类型', trigger: 'blur'
27 | }],
28 | name: [{
29 | required: true, message: '请输入部门名称', trigger: 'blur'
30 | }, {
31 | min: 4, max: 20, message: '长度在 4 到 20 个字符', trigger: 'blur'
32 | }],
33 | sortNum: [{
34 | required: true, message: '请输入部门编号', trigger: 'blur'
35 | }]
36 | }
37 | },
38 | queryAllUsers() {
39 | this.users = []
40 | DeptAPI.queryAllDeptUsers(this.detail.id).then(users => {
41 | this.users = users
42 | })
43 | },
44 | queryAllRoles() {
45 | this.roles = []
46 | DeptAPI.queryAllDeptRoles(this.detail.id).then(roles => {
47 | this.roles = roles
48 | })
49 | },
50 | getParentDeptName(id) {
51 | this.parentDeptName = ''
52 | if (!id) return
53 | DeptAPI.queryDeptById(id).then(dept => {
54 | this.parentDeptName = dept.name
55 | })
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/views/system-management/dictionary-type/add.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | 保存
17 | 取消
18 |
19 |
20 |
21 |
22 |
58 |
59 |
62 |
--------------------------------------------------------------------------------
/src/views/system-management/dictionary-type/check.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
返回
4 |
5 |
6 |
7 | {{ detail.id }}
8 | {{ detail.name }}
9 | {{ detail.code }}
10 | {{ detail.sortNum }}
11 | {{ detail.remark }}
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
38 |
39 |
44 |
--------------------------------------------------------------------------------
/src/views/system-management/dictionary-type/edit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | 保存
20 | 取消
21 |
22 |
23 |
24 |
25 |
67 |
68 |
71 |
--------------------------------------------------------------------------------
/src/views/system-management/dictionary-type/main.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
34 |
--------------------------------------------------------------------------------
/src/views/system-management/dictionary-type/mixins.js:
--------------------------------------------------------------------------------
1 | export default {
2 | methods: {
3 | initForm() {
4 | return {
5 | id: null,
6 | token: null,
7 | parentId: null,
8 | category: 1,
9 | type: '',
10 | name: '',
11 | code: '',
12 | sortNum: '',
13 | remark: ''
14 | }
15 | },
16 | initRules() {
17 | return {
18 | name: [{
19 | required: true, message: '请输入字典分类名称', trigger: 'blur'
20 | }, {
21 | min: 4, max: 20, message: '长度在 4 到 20 个字符', trigger: 'blur'
22 | }],
23 | sortNum: [{
24 | required: true, message: '请输入字典分类编号', trigger: 'blur'
25 | }]
26 | }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/views/system-management/dictionary/add.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | 保存
26 | 取消
27 |
28 |
29 |
30 |
31 |
77 |
78 |
83 |
--------------------------------------------------------------------------------
/src/views/system-management/dictionary/check.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
返回
4 |
5 |
6 |
7 | {{ detail.id }}
8 | {{ parentDictionaryName }}
9 | {{ detail.category | translateDicCategory }}
10 | {{ getDictionaryTypeName(detail.type) }}
11 | {{ detail.name }}
12 | {{ detail.code }}
13 | {{ detail.sortNum }}
14 | {{ detail.remark }}
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
40 |
41 |
46 |
--------------------------------------------------------------------------------
/src/views/system-management/dictionary/edit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | 保存
23 | 取消
24 |
25 |
26 |
27 |
28 |
77 |
78 |
83 |
--------------------------------------------------------------------------------
/src/views/system-management/dictionary/mixins.js:
--------------------------------------------------------------------------------
1 | import { mapGetters } from 'vuex'
2 | import * as DictionaryAPI from '@/api/system-management/dictionary'
3 |
4 | export default {
5 | props: {
6 | category: {
7 | required: true,
8 | type: String,
9 | default: () => {}
10 | },
11 | detail: {
12 | required: false,
13 | type: Object,
14 | default: () => {}
15 | }
16 | },
17 | data() {
18 | return {
19 | parentDictionaryName: '',
20 | dictionaryTypeList: []
21 | }
22 | },
23 | computed: {
24 | ...mapGetters([
25 | 'dictionaries'
26 | ])
27 | },
28 | methods: {
29 | initForm() {
30 | return {
31 | id: null,
32 | token: null,
33 | parentId: null,
34 | category: 2,
35 | type: '',
36 | name: '',
37 | code: '',
38 | sortNum: '',
39 | remark: ''
40 | }
41 | },
42 | initRules() {
43 | return {
44 | category: [{
45 | required: true, message: '字典类别为必填项', trigger: 'change'
46 | }],
47 | type: [{
48 | required: true, message: '请选择字典类型', trigger: 'change'
49 | }],
50 | name: [{
51 | required: true, message: '请输入字典名称', trigger: 'blur'
52 | }, {
53 | min: 4, max: 20, message: '长度在 4 到 20 个字符', trigger: 'blur'
54 | }],
55 | sortNum: [{
56 | required: true, message: '请输入字典编号', trigger: 'blur'
57 | }]
58 | }
59 | },
60 | queryAllDictionaryType() {
61 | DictionaryAPI.queryAllDictionaries([{ field: 'category', value: 1 }]).then((list) => {
62 | this.dictionaryTypeList = list
63 | }, () => {
64 | this.dictionaryTypeList = []
65 | })
66 | },
67 | getDictionaryTypeName(type) {
68 | const dictionary = this.dictionaryTypeList.find(item => item.id === type)
69 | if (dictionary) {
70 | return dictionary.name
71 | }
72 | return type
73 | },
74 | getParentDictionaryName(id) {
75 | this.parentDictionaryName = ''
76 | if (!id || id === 'root') return
77 | DictionaryAPI.queryDictionaryById(id).then(dictionary => {
78 | this.parentDictionaryName = dictionary.name
79 | })
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/views/system-management/dictionary/multiMain.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
34 |
--------------------------------------------------------------------------------
/src/views/system-management/dictionary/singleMain.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
34 |
--------------------------------------------------------------------------------
/src/views/system-management/group/add.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | 保存
14 | 取消
15 |
16 |
17 |
18 |
19 |
53 |
54 |
57 |
--------------------------------------------------------------------------------
/src/views/system-management/group/main.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
34 |
--------------------------------------------------------------------------------
/src/views/system-management/group/mixins.js:
--------------------------------------------------------------------------------
1 | import * as GroupAPI from '@/api/system-management/group'
2 |
3 | export default {
4 | props: {
5 | detail: {
6 | required: false,
7 | type: Object,
8 | default: () => {}
9 | }
10 | },
11 | data() {
12 | return {
13 | isUserGroup: this.$route.query.category === '' + 1,
14 | isRoleGroup: this.$route.query.category === '' + 2
15 | }
16 | },
17 | methods: {
18 | initForm() {
19 | return {
20 | id: null,
21 | // 新增操作,根据路由决定该值的实际取值,分组可面向用户、角色等
22 | // 其他操作不允许修改该字段
23 | category: this.$route.query.category,
24 | name: '',
25 | sortNum: '',
26 | remark: ''
27 | }
28 | },
29 | initRules() {
30 | return {
31 | category: [{
32 | required: true, message: '请输入分组类型', trigger: 'blur'
33 | }],
34 | name: [{
35 | required: true, message: '请输入分组名称', trigger: 'blur'
36 | }, {
37 | min: 4, max: 20, message: '长度在 4 到 20 个字符', trigger: 'blur'
38 | }],
39 | sortNum: [{
40 | required: true, message: '请输入分组编号', trigger: 'blur'
41 | }]
42 | }
43 | },
44 | queryAllUsers() {
45 | this.users = []
46 | let queryAllUsers = null
47 | if (this.isUserGroup) {
48 | queryAllUsers = GroupAPI.queryAllUserGroupUsers // 用户分组下的所有用户
49 | }
50 | if (this.isRoleGroup) {
51 | queryAllUsers = GroupAPI.queryAllRoleGroupUsers // 角色分组下的所有用户
52 | }
53 | queryAllUsers(this.detail.id).then(users => {
54 | this.users = users
55 | })
56 | },
57 | queryAllGroups() {
58 | this.groups = []
59 | let queryAllGroups = null
60 | if (this.isUserGroup) {
61 | queryAllGroups = GroupAPI.queryAllRoleGroups // 用户分组下的所有角色分组
62 | }
63 | if (this.isRoleGroup) {
64 | queryAllGroups = GroupAPI.queryAllUserGroups // 角色分组下的所有用户分组
65 | }
66 | queryAllGroups(this.detail.id).then(groups => {
67 | this.groups = groups
68 | })
69 | },
70 | queryAllRoles() {
71 | this.roles = []
72 | GroupAPI.queryAllGroupRoles(this.detail.id).then(roles => {
73 | this.roles = roles
74 | })
75 | },
76 | getGroupName() {
77 | if (this.isUserGroup) return '关联的角色组信息'
78 | if (this.isRoleGroup) return '关联的用户组信息'
79 | return '未知分组信息'
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/views/system-management/menu/check.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
返回
4 |
5 |
6 |
7 | {{ detail.id }}
8 | {{ parentMenuName }}
9 | {{ detail.sortNum }}
10 | {{ detail.name }}
11 | {{ detail.icon }}
12 | {{ detail.remark }}
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
61 |
62 |
67 |
--------------------------------------------------------------------------------
/src/views/system-management/menu/main.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
33 |
--------------------------------------------------------------------------------
/src/views/system-management/menu/mixins.js:
--------------------------------------------------------------------------------
1 | import * as MenuAPI from '@/api/system-management/menu'
2 |
3 | export default {
4 | data() {
5 | return {
6 | parentMenuName: '',
7 | roles: [],
8 | securities: []
9 | }
10 | },
11 | methods: {
12 | queryMenuRoles() {
13 | this.roles = []
14 | MenuAPI.queryAllMenuRole(this.detail.id).then(roles => { this.roles = roles })
15 | },
16 | queryMenuSecurities() {
17 | this.securities = []
18 | MenuAPI.queryAllMenuSecurities(this.detail.id).then(securities => {
19 | this.securities = securities
20 | })
21 | },
22 | getParentMenuName(id) {
23 | this.parentMenuName = ''
24 | if (!id) return
25 | MenuAPI.queryMenuById(id).then(menu => {
26 | this.parentMenuName = menu.name
27 | })
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/views/system-management/role/add.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | 保存
14 | 取消
15 |
16 |
17 |
18 |
19 |
61 |
62 |
65 |
--------------------------------------------------------------------------------
/src/views/system-management/role/main.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
34 |
--------------------------------------------------------------------------------
/src/views/system-management/role/mixins.js:
--------------------------------------------------------------------------------
1 | import * as RoleAPI from '@/api/system-management/role'
2 | import * as MenuAPI from '@/api/system-management/menu'
3 | import { asyncMenuMap } from '@/router'
4 |
5 | export default {
6 | data() {
7 | return {
8 | menusTree: [],
9 | users: [],
10 | groups: [],
11 | depts: []
12 | }
13 | },
14 | methods: {
15 | initForm() {
16 | return {
17 | id: null,
18 | token: null,
19 | name: '',
20 | sortNum: '',
21 | remark: ''
22 | }
23 | },
24 | initRules() {
25 | return {
26 | name: [{
27 | required: true, message: '请输入角色名称', trigger: 'blur'
28 | }, {
29 | min: 4, max: 20, message: '长度在 4 到 20 个字符', trigger: 'blur'
30 | }],
31 | sortNum: [{
32 | required: true, message: '请输入角色编号', trigger: 'blur'
33 | }]
34 | }
35 | },
36 | queryAllUsers() {
37 | this.users = []
38 | RoleAPI.queryAllRoleUsers(this.detail.id).then(users => {
39 | this.users = users
40 | })
41 | },
42 | queryAllGroups() {
43 | this.groups = []
44 | RoleAPI.queryAllRoleGroups(this.detail.id).then(groups => {
45 | this.groups = groups
46 | })
47 | },
48 | queryAllDepts() {
49 | this.depts = []
50 | RoleAPI.queryAllRoleDepts(this.detail.id).then(depts => {
51 | this.depts = depts
52 | })
53 | },
54 | filterNodeHandler(value, data) {
55 | if (!value) return true
56 | return data.name.indexOf(value) !== -1
57 | },
58 | initMenus() {
59 | MenuAPI.queryAllMenus({}).then(allMenus => {
60 | const menusTree = []
61 | asyncMenuMap.forEach(router => {
62 | menusTree.push(MenuAPI.createMenuTree(allMenus, router, null))
63 | })
64 | this.menusTree = menusTree
65 | const needSync = this.menusTree.some(menu => {
66 | return MenuAPI.syncMenuVoter(allMenus, menu)
67 | })
68 | if (needSync) {
69 | this.$notify({
70 | title: '提示',
71 | type: 'warning',
72 | message: '检测到您需要同步本地菜单信息树至服务端',
73 | duration: 0
74 | })
75 | }
76 |
77 | RoleAPI.queryAllRoleMenus(this.detail.id).then(roleMenus => {
78 | const checkedMenus = []
79 | roleMenus.forEach(item => {
80 | checkedMenus.push(item.id)
81 | })
82 | this.$refs['menusTree'].setCheckedKeys(checkedMenus)
83 | })
84 | })
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/views/system-management/role/query.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | 重置
15 | 查询
16 |
17 |
18 |
19 |
20 | 角色列表
21 |
22 |
23 | 查看
24 | 新增
25 | 编辑
26 | 删除
27 |
28 |
29 |
30 |
31 |
32 | { selected = row }" @row-dblclick="$emit('option-changed','check', selected)" @sort-change="sortChangeHandler">
33 |
34 |
35 | {{ scope.row.createdDate | parseTime }}
36 |
37 |
38 | {{ scope.row.modifiedDate | parseTime }}
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
88 |
89 |
98 |
--------------------------------------------------------------------------------
/src/views/system-management/security/add.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | 保存
14 | 取消
15 |
16 |
17 |
18 |
19 |
60 |
61 |
64 |
--------------------------------------------------------------------------------
/src/views/system-management/security/check.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
返回
4 |
5 |
6 |
7 | {{ detail.id }}
8 | {{ detail.securityDef }}
9 | {{ detail.name }}
10 | {{ detail.remark }}
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
42 |
43 |
48 |
--------------------------------------------------------------------------------
/src/views/system-management/security/edit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
返回
4 |
5 |
6 |
7 | 基础信息
8 |
9 | 保存
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
75 |
76 |
81 |
--------------------------------------------------------------------------------
/src/views/system-management/security/main.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
34 |
--------------------------------------------------------------------------------
/src/views/system-management/security/mixins.js:
--------------------------------------------------------------------------------
1 | export default {
2 | methods: {
3 | initForm() {
4 | return {
5 | id: null,
6 | securityDef: null,
7 | name: '',
8 | remark: ''
9 | }
10 | },
11 | initRules() {
12 | return {
13 | securityDef: [{
14 | required: true, message: '请输入资源定义', trigger: 'blur'
15 | }, {
16 | min: 1, max: 200, message: '长度在 1 到 200 个字符', trigger: 'blur'
17 | }],
18 | name: [{
19 | required: true, message: '请输入资源名称', trigger: 'blur'
20 | }, {
21 | min: 4, max: 20, message: '长度在 4 到 20 个字符', trigger: 'blur'
22 | }],
23 | remark: [{
24 | min: 0, max: 200, message: '长度在 0 到 200 个字符', trigger: 'blur'
25 | }]
26 | }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/views/system-management/user/main.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
35 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 |
4 | function resolve(dir) {
5 | return path.join(__dirname, dir)
6 | }
7 |
8 | const port = 9527 // TODO: change to Settings
9 | const appName = 'element-admin'
10 |
11 | module.exports = {
12 | /**
13 | * You can set by yourself according to actual condition
14 | * You will need to set this if you plan to deploy your site under a sub path,
15 | * for example GitHub pages. If you plan to deploy your site to https://foo.github.io/bar/,
16 | * then assetsPublicPath should be set to "/bar/".
17 | * In most cases please use '/' !!!
18 | * Detail https://cli.vuejs.org/config/#baseurl
19 | */
20 | publicPath: '/',
21 | outputDir: 'dist',
22 | assetsDir: 'public',
23 | lintOnSave: process.env.NODE_ENV !== 'production',
24 | productionSourceMap: false,
25 | devServer: {
26 | port: port,
27 | open: true,
28 | overlay: {
29 | warnings: false,
30 | errors: true
31 | },
32 | proxy: {
33 | '/admin': {
34 | // target: `http://localhost:${port}/mock`,
35 | target: 'http://localhost:8080',
36 | changeOrigin: true,
37 | pathRewrite: {
38 | '^/' : '/'
39 | }
40 | }
41 | }
42 | },
43 | configureWebpack: {
44 | // We provide the app's title in Webpack's name field, so that
45 | // it can be accessed in index.html to inject the correct title.
46 | name: appName,
47 | resolve: {
48 | alias: {
49 | '@': resolve('src')
50 | }
51 | }
52 | },
53 | chainWebpack(config) {
54 | config.module
55 | .rule('svg')
56 | .exclude.add(resolve('src/icons'))
57 | .end()
58 | config.module
59 | .rule('icons')
60 | .test(/\.svg$/)
61 | .include.add(resolve('src/icons'))
62 | .end()
63 | .use('svg-sprite-loader')
64 | .loader('svg-sprite-loader')
65 | .options({
66 | symbolId: 'icon-[name]'
67 | })
68 | .end()
69 | }
70 | }
71 |
--------------------------------------------------------------------------------