commit:微服务uaa版本
@@ -0,0 +1,2 @@
|
|||||||
|
> 1%
|
||||||
|
last 2 versions
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[*.{js,jsx,ts,tsx,vue}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
env: {
|
||||||
|
node: true
|
||||||
|
},
|
||||||
|
'extends': [
|
||||||
|
'plugin:vue/essential',
|
||||||
|
'@vue/standard'
|
||||||
|
],
|
||||||
|
parserOptions: {
|
||||||
|
parser: 'babel-eslint'
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||||
|
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||||
|
'semi': ['off', 'always'],
|
||||||
|
'prefer-promise-reject-errors': ['error', { 'allowEmptyReject': true }],
|
||||||
|
'no-trailing-spaces': ['error', { 'skipBlankLines': true }],
|
||||||
|
'prefer-const': ['off'],
|
||||||
|
'quote-props': ['off'],
|
||||||
|
'object-curly-spacing': ['off'],
|
||||||
|
'dot-notation': ['off'],
|
||||||
|
'lines-between-class-members': ['off'],
|
||||||
|
// 'no-undef': ['off', 'always'],
|
||||||
|
// 'no-unused-vars': ['off', 'always'],
|
||||||
|
'no-new-func': ['off', 'always'],
|
||||||
|
'no-console': ['off']
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: [
|
||||||
|
'**/__tests__/*.{j,t}s?(x)',
|
||||||
|
'**/tests/unit/**/*.spec.{j,t}s?(x)'
|
||||||
|
],
|
||||||
|
env: {
|
||||||
|
jest: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
21
orange-demo-uaa/orange-demo-multi-service-uaa-admin-web/.gitignore
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
.DS_Store
|
||||||
|
node_modules
|
||||||
|
/dist
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
|
||||||
|
# Log files
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
## 橙单代码生成器
|
||||||
|
### 构建命令
|
||||||
|
``` bash
|
||||||
|
# install dependencies
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# serve with hot reload at localhost:8080
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# build for production with minification
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# run all tests
|
||||||
|
npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
### 官方文档:[http://101.200.178.51/](http://101.200.178.51/)
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
module.exports = {
|
||||||
|
presets: [
|
||||||
|
'@vue/cli-plugin-babel/preset'
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
preset: '@vue/cli-plugin-unit-jest'
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"name": "orange-single-page-project",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"serve": "vue-cli-service serve",
|
||||||
|
"dev": "vue-cli-service serve",
|
||||||
|
"build": "vue-cli-service build",
|
||||||
|
"test:unit": "vue-cli-service test:unit",
|
||||||
|
"lint": "vue-cli-service lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^0.18.0",
|
||||||
|
"echarts": "^4.2.1",
|
||||||
|
"element-ui": "^2.13.0",
|
||||||
|
"jquery": "^3.3.1",
|
||||||
|
"jsencrypt": "^3.0.0-rc.1",
|
||||||
|
"json-bigint": "^0.3.0",
|
||||||
|
"layui-layer": "^1.0.9",
|
||||||
|
"lodash": "^4.17.5",
|
||||||
|
"core-js": "^3.6.4",
|
||||||
|
"register-service-worker": "^1.6.2",
|
||||||
|
"sortablejs": "^1.7.0",
|
||||||
|
"v-charts": "^1.19.0",
|
||||||
|
"vue": "^2.6.11",
|
||||||
|
"vue-router": "^3.1.5",
|
||||||
|
"vuex": "^3.1.2",
|
||||||
|
"wangeditor": "^3.1.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@vue/cli-plugin-babel": "~4.2.0",
|
||||||
|
"@vue/cli-plugin-eslint": "~4.2.0",
|
||||||
|
"@vue/cli-plugin-pwa": "~4.2.0",
|
||||||
|
"@vue/cli-plugin-router": "~4.2.0",
|
||||||
|
"@vue/cli-plugin-unit-jest": "~4.2.0",
|
||||||
|
"@vue/cli-plugin-vuex": "~4.2.0",
|
||||||
|
"@vue/cli-service": "~4.2.0",
|
||||||
|
"@vue/eslint-config-standard": "^5.1.0",
|
||||||
|
"@vue/test-utils": "1.0.0-beta.31",
|
||||||
|
"babel-eslint": "^10.0.3",
|
||||||
|
"eslint": "^6.7.2",
|
||||||
|
"eslint-plugin-import": "^2.20.1",
|
||||||
|
"eslint-plugin-node": "^11.0.0",
|
||||||
|
"eslint-plugin-promise": "^4.2.1",
|
||||||
|
"eslint-plugin-standard": "^4.0.0",
|
||||||
|
"eslint-plugin-vue": "^6.1.2",
|
||||||
|
"lint-staged": "^9.5.0",
|
||||||
|
"node-sass": "^4.13.1",
|
||||||
|
"sass-loader": "^7.3.1",
|
||||||
|
"vue-template-compiler": "^2.6.11"
|
||||||
|
},
|
||||||
|
"gitHooks": {
|
||||||
|
"pre-commit": "lint-staged"
|
||||||
|
},
|
||||||
|
"lint-staged": {
|
||||||
|
"*.{js,jsx,vue}": [
|
||||||
|
"vue-cli-service lint",
|
||||||
|
"git add"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 9.2 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 799 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
@@ -0,0 +1,149 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||||
|
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16.000000pt" height="16.000000pt" viewBox="0 0 16.000000 16.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet">
|
||||||
|
<metadata>
|
||||||
|
Created by potrace 1.11, written by Peter Selinger 2001-2013
|
||||||
|
</metadata>
|
||||||
|
<g transform="translate(0.000000,16.000000) scale(0.000320,-0.000320)"
|
||||||
|
fill="#000000" stroke="none">
|
||||||
|
<path d="M18 46618 c45 -75 122 -207 122 -211 0 -2 25 -45 55 -95 30 -50 55
|
||||||
|
-96 55 -102 0 -5 5 -10 10 -10 6 0 10 -4 10 -9 0 -5 73 -135 161 -288 89 -153
|
||||||
|
173 -298 187 -323 14 -25 32 -57 41 -72 88 -149 187 -324 189 -335 2 -7 8 -13
|
||||||
|
13 -13 5 0 9 -4 9 -10 0 -5 46 -89 103 -187 175 -302 490 -846 507 -876 8 -16
|
||||||
|
20 -36 25 -45 28 -46 290 -498 339 -585 13 -23 74 -129 136 -236 61 -107 123
|
||||||
|
-215 137 -240 14 -25 29 -50 33 -56 5 -5 23 -37 40 -70 18 -33 38 -67 44 -75
|
||||||
|
11 -16 21 -33 63 -109 14 -25 29 -50 33 -56 4 -5 21 -35 38 -65 55 -100 261
|
||||||
|
-455 269 -465 4 -5 14 -21 20 -35 15 -29 41 -75 103 -180 24 -41 52 -88 60
|
||||||
|
-105 9 -16 57 -100 107 -185 112 -193 362 -626 380 -660 8 -14 23 -38 33 -55
|
||||||
|
11 -16 23 -37 27 -45 4 -8 26 -46 48 -85 23 -38 53 -90 67 -115 46 -81 64
|
||||||
|
-113 178 -310 62 -107 121 -210 132 -227 37 -67 56 -99 85 -148 16 -27 32 -57
|
||||||
|
36 -65 4 -8 15 -27 25 -42 9 -15 53 -89 96 -165 44 -76 177 -307 296 -513 120
|
||||||
|
-206 268 -463 330 -570 131 -227 117 -203 200 -348 36 -62 73 -125 82 -140 10
|
||||||
|
-15 21 -34 25 -42 4 -8 20 -37 36 -65 17 -27 38 -65 48 -82 49 -85 64 -111 87
|
||||||
|
-153 13 -25 28 -49 32 -55 4 -5 78 -134 165 -285 87 -151 166 -288 176 -305
|
||||||
|
10 -16 26 -43 35 -59 9 -17 125 -217 257 -445 132 -229 253 -441 270 -471 17
|
||||||
|
-30 45 -79 64 -108 18 -29 33 -54 33 -57 0 -2 20 -37 44 -77 24 -40 123 -212
|
||||||
|
221 -383 97 -170 190 -330 205 -355 16 -25 39 -65 53 -90 13 -25 81 -144 152
|
||||||
|
-265 70 -121 137 -238 150 -260 12 -22 37 -65 55 -95 18 -30 43 -73 55 -95 12
|
||||||
|
-22 48 -85 80 -140 77 -132 163 -280 190 -330 13 -22 71 -123 130 -225 59
|
||||||
|
-102 116 -199 126 -217 10 -17 29 -50 43 -72 15 -22 26 -43 26 -45 0 -2 27
|
||||||
|
-50 60 -106 33 -56 60 -103 60 -105 0 -2 55 -98 90 -155 8 -14 182 -316 239
|
||||||
|
-414 13 -22 45 -79 72 -124 27 -46 49 -86 49 -89 0 -2 14 -24 30 -48 16 -24
|
||||||
|
30 -46 30 -49 0 -5 74 -135 100 -176 5 -8 24 -42 43 -75 50 -88 58 -101 262
|
||||||
|
-455 104 -179 199 -345 213 -370 14 -25 28 -49 32 -55 4 -5 17 -26 28 -45 10
|
||||||
|
-19 62 -109 114 -200 114 -197 133 -230 170 -295 16 -27 33 -57 38 -65 17 -28
|
||||||
|
96 -165 103 -180 4 -8 16 -28 26 -45 10 -16 77 -131 148 -255 72 -124 181
|
||||||
|
-313 243 -420 62 -107 121 -209 131 -227 35 -62 323 -560 392 -678 38 -66 83
|
||||||
|
-145 100 -175 16 -30 33 -59 37 -65 4 -5 17 -27 29 -47 34 -61 56 -100 90
|
||||||
|
-156 17 -29 31 -55 31 -57 0 -2 17 -32 39 -67 21 -35 134 -229 251 -433 117
|
||||||
|
-203 235 -407 261 -451 27 -45 49 -85 49 -88 0 -4 8 -19 19 -34 15 -21 200
|
||||||
|
-341 309 -533 10 -19 33 -58 51 -87 17 -29 31 -54 31 -56 0 -2 25 -44 55 -94
|
||||||
|
30 -50 55 -95 55 -98 0 -4 6 -15 14 -23 7 -9 27 -41 43 -71 17 -30 170 -297
|
||||||
|
342 -594 171 -296 311 -542 311 -547 0 -5 5 -9 10 -9 6 0 10 -4 10 -10 0 -5
|
||||||
|
22 -47 49 -92 27 -46 58 -99 68 -118 24 -43 81 -140 93 -160 5 -8 66 -114 135
|
||||||
|
-235 69 -121 130 -227 135 -235 12 -21 259 -447 283 -490 10 -19 28 -47 38
|
||||||
|
-62 11 -14 19 -29 19 -32 0 -3 37 -69 83 -148 99 -170 305 -526 337 -583 13
|
||||||
|
-22 31 -53 41 -70 11 -16 22 -37 26 -45 7 -14 82 -146 103 -180 14 -24 181
|
||||||
|
-311 205 -355 13 -22 46 -80 75 -130 29 -49 64 -110 78 -135 14 -25 51 -88 82
|
||||||
|
-140 31 -52 59 -102 63 -110 4 -8 18 -33 31 -55 205 -353 284 -489 309 -535
|
||||||
|
17 -30 45 -78 62 -106 18 -28 36 -60 39 -72 4 -12 12 -22 17 -22 5 0 9 -4 9
|
||||||
|
-10 0 -5 109 -197 241 -427 133 -230 250 -431 259 -448 51 -90 222 -385 280
|
||||||
|
-485 37 -63 78 -135 92 -160 14 -25 67 -117 118 -205 51 -88 101 -175 111
|
||||||
|
-193 34 -58 55 -95 149 -257 51 -88 101 -173 110 -190 9 -16 76 -131 147 -255
|
||||||
|
72 -124 140 -241 151 -260 61 -108 281 -489 355 -615 38 -66 77 -133 87 -150
|
||||||
|
35 -63 91 -161 100 -175 14 -23 99 -169 128 -220 54 -97 135 -235 142 -245 4
|
||||||
|
-5 20 -32 35 -60 26 -48 238 -416 276 -480 10 -16 26 -46 37 -65 30 -53 382
|
||||||
|
-661 403 -695 10 -16 22 -37 26 -45 4 -8 26 -48 50 -88 24 -41 43 -75 43 -77
|
||||||
|
0 -2 22 -40 50 -85 27 -45 50 -84 50 -86 0 -3 38 -69 83 -147 84 -142 302
|
||||||
|
-520 340 -587 10 -19 34 -60 52 -90 18 -30 44 -75 57 -100 14 -25 45 -79 70
|
||||||
|
-120 25 -41 56 -96 70 -121 14 -25 77 -133 138 -240 62 -107 122 -210 132
|
||||||
|
-229 25 -43 310 -535 337 -581 11 -19 26 -45 34 -59 17 -32 238 -414 266 -460
|
||||||
|
11 -19 24 -41 28 -49 3 -7 75 -133 160 -278 84 -146 153 -269 153 -274 0 -5 5
|
||||||
|
-9 10 -9 6 0 10 -4 10 -10 0 -5 82 -150 181 -322 182 -314 201 -346 240 -415
|
||||||
|
12 -21 80 -139 152 -263 71 -124 141 -245 155 -270 14 -25 28 -49 32 -55 6 -8
|
||||||
|
145 -248 220 -380 37 -66 209 -362 229 -395 11 -19 24 -42 28 -49 4 -8 67
|
||||||
|
-118 140 -243 73 -125 133 -230 133 -233 0 -2 15 -28 33 -57 19 -29 47 -78 64
|
||||||
|
-108 17 -30 53 -93 79 -139 53 -90 82 -141 157 -272 82 -142 115 -199 381
|
||||||
|
-659 142 -245 268 -463 281 -485 12 -22 71 -125 132 -230 60 -104 172 -298
|
||||||
|
248 -430 76 -132 146 -253 156 -270 11 -16 22 -36 26 -44 3 -8 30 -54 60 -103
|
||||||
|
29 -49 53 -91 53 -93 0 -3 18 -34 40 -70 22 -36 40 -67 40 -69 0 -2 37 -66 81
|
||||||
|
-142 45 -77 98 -168 119 -204 20 -36 47 -81 58 -100 12 -19 27 -47 33 -62 6
|
||||||
|
-16 15 -28 20 -28 5 0 9 -4 9 -9 0 -6 63 -118 140 -251 77 -133 140 -243 140
|
||||||
|
-245 0 -2 18 -33 41 -70 22 -37 49 -83 60 -101 10 -19 29 -51 40 -71 25 -45
|
||||||
|
109 -189 126 -218 7 -11 17 -29 22 -40 6 -11 22 -38 35 -60 14 -22 37 -62 52
|
||||||
|
-90 14 -27 35 -62 45 -77 11 -14 19 -29 19 -32 0 -3 18 -35 40 -71 22 -36 40
|
||||||
|
-67 40 -69 0 -2 19 -35 42 -72 23 -38 55 -94 72 -124 26 -47 139 -244 171
|
||||||
|
-298 6 -9 21 -36 34 -60 28 -48 37 -51 51 -19 6 12 19 36 29 52 10 17 27 46
|
||||||
|
38 65 11 19 104 181 208 360 103 179 199 345 213 370 14 25 42 74 64 109 21
|
||||||
|
34 38 65 38 67 0 2 18 33 40 69 22 36 40 67 40 69 0 3 177 310 199 346 16 26
|
||||||
|
136 234 140 244 2 5 25 44 52 88 27 44 49 81 49 84 0 2 18 34 40 70 22 36 40
|
||||||
|
67 40 69 0 2 20 36 43 77 35 58 169 289 297 513 9 17 50 86 90 155 40 69 86
|
||||||
|
150 103 180 16 30 35 62 41 70 6 8 16 24 22 35 35 64 72 129 167 293 59 100
|
||||||
|
116 199 127 220 11 20 30 53 41 72 43 72 1070 1850 1121 1940 14 25 65 113
|
||||||
|
113 195 48 83 96 166 107 185 10 19 28 50 38 68 11 18 73 124 137 235 64 111
|
||||||
|
175 303 246 427 71 124 173 299 225 390 52 91 116 202 143 248 27 45 49 85 49
|
||||||
|
89 0 4 6 14 14 22 7 9 28 43 46 76 26 47 251 436 378 655 11 19 29 51 40 70
|
||||||
|
11 19 101 176 201 348 99 172 181 317 181 323 0 5 5 9 10 9 6 0 10 5 10 11 0
|
||||||
|
6 8 23 18 37 11 15 32 52 49 82 16 30 130 228 253 440 122 212 234 405 248
|
||||||
|
430 13 25 39 70 57 100 39 65 69 117 130 225 25 44 50 87 55 95 12 19 78 134
|
||||||
|
220 380 61 107 129 224 150 260 161 277 222 382 246 425 15 28 47 83 71 123
|
||||||
|
24 41 43 78 43 83 0 5 4 9 8 9 4 0 13 12 19 28 7 15 23 45 36 67 66 110 277
|
||||||
|
478 277 483 0 3 6 13 14 21 7 9 27 41 43 71 17 30 45 80 63 110 34 57 375 649
|
||||||
|
394 685 6 11 16 27 22 35 6 8 26 42 44 75 18 33 41 74 51 90 10 17 24 41 32
|
||||||
|
55 54 97 72 128 88 152 11 14 19 28 19 30 0 3 79 141 175 308 96 167 175 305
|
||||||
|
175 308 0 3 6 13 14 21 7 9 26 39 41 66 33 60 276 483 338 587 24 40 46 80 50
|
||||||
|
88 4 8 13 24 20 35 14 23 95 163 125 215 11 19 52 91 92 160 40 69 80 139 90
|
||||||
|
155 9 17 103 179 207 360 105 182 200 346 211 365 103 181 463 802 489 845 7
|
||||||
|
11 15 27 19 35 4 8 29 51 55 95 64 110 828 1433 848 1470 9 17 24 41 33 55 9
|
||||||
|
14 29 48 45 77 15 28 52 93 82 145 30 51 62 107 71 123 17 30 231 398 400 690
|
||||||
|
51 88 103 179 115 202 12 23 26 48 32 55 6 7 24 38 40 68 17 30 61 107 98 170
|
||||||
|
37 63 84 144 103 180 19 36 41 72 48 81 8 8 14 18 14 21 0 4 27 51 59 106 32
|
||||||
|
55 72 124 89 154 16 29 71 125 122 213 51 88 104 180 118 205 13 25 28 50 32
|
||||||
|
55 4 6 17 26 28 45 11 19 45 80 77 135 31 55 66 116 77 135 11 19 88 152 171
|
||||||
|
295 401 694 620 1072 650 1125 11 19 87 152 170 295 83 143 158 273 166 288 9
|
||||||
|
16 21 36 26 45 6 9 31 52 55 96 25 43 54 94 66 115 11 20 95 164 186 321 91
|
||||||
|
157 173 299 182 315 9 17 26 46 37 65 12 19 66 114 121 210 56 96 108 186 117
|
||||||
|
200 8 14 24 40 34 59 24 45 383 664 412 713 5 9 17 29 26 45 15 28 120 210
|
||||||
|
241 419 36 61 68 117 72 125 4 8 12 23 19 34 35 57 245 420 262 453 11 20 35
|
||||||
|
61 53 90 17 29 32 54 32 56 0 3 28 51 62 108 33 57 70 119 80 138 10 19 23 42
|
||||||
|
28 50 5 8 32 53 59 100 27 47 149 258 271 470 122 212 234 405 248 430 30 53
|
||||||
|
62 108 80 135 6 11 15 27 19 35 4 8 85 150 181 315 96 165 187 323 202 350 31
|
||||||
|
56 116 202 130 225 5 8 25 42 43 75 19 33 92 159 162 280 149 257 157 271 202
|
||||||
|
350 19 33 38 67 43 75 9 14 228 392 275 475 12 22 55 96 95 165 40 69 80 139
|
||||||
|
90 155 24 42 202 350 221 383 9 15 27 47 41 72 14 25 75 131 136 236 61 106
|
||||||
|
121 210 134 232 99 172 271 470 279 482 5 8 23 40 40 70 18 30 81 141 142 245
|
||||||
|
60 105 121 210 135 235 14 25 71 124 127 220 56 96 143 247 194 335 51 88 96
|
||||||
|
167 102 175 14 24 180 311 204 355 23 43 340 590 356 615 5 8 50 87 101 175
|
||||||
|
171 301 517 898 582 1008 25 43 46 81 46 83 0 2 12 23 27 47 14 23 40 67 56
|
||||||
|
97 16 30 35 62 42 70 7 8 15 22 18 30 4 8 20 38 37 65 16 28 33 57 37 65 6 12
|
||||||
|
111 196 143 250 5 8 55 95 112 193 57 98 113 195 126 215 12 20 27 46 32 57 6
|
||||||
|
11 14 27 20 35 5 8 76 130 156 270 80 140 165 287 187 325 23 39 52 90 66 115
|
||||||
|
13 25 30 52 37 61 8 8 14 18 14 21 0 4 41 77 92 165 50 87 175 302 276 478
|
||||||
|
101 176 208 360 236 408 28 49 67 117 86 152 19 35 41 70 48 77 6 6 12 15 12
|
||||||
|
19 0 7 124 224 167 291 12 21 23 40 23 42 0 2 21 40 46 83 26 43 55 92 64 109
|
||||||
|
54 95 327 568 354 614 19 30 45 75 59 100 71 128 82 145 89 148 4 2 8 8 8 13
|
||||||
|
0 5 42 82 94 172 311 538 496 858 518 897 14 25 40 70 58 100 18 30 42 71 53
|
||||||
|
90 10 19 79 139 152 265 73 127 142 246 153 265 10 19 43 76 72 125 29 50 63
|
||||||
|
108 75 130 65 116 80 140 87 143 4 2 8 8 8 12 0 8 114 212 140 250 6 8 14 24
|
||||||
|
20 35 5 11 54 97 108 190 l100 170 -9611 3 c-5286 1 -9614 -1 -9618 -5 -5 -6
|
||||||
|
-419 -719 -619 -1068 -89 -155 -267 -463 -323 -560 -38 -66 -81 -140 -95 -165
|
||||||
|
-31 -56 -263 -457 -526 -910 -110 -190 -224 -388 -254 -440 -29 -52 -61 -109
|
||||||
|
-71 -125 -23 -39 -243 -420 -268 -465 -11 -19 -204 -352 -428 -740 -224 -388
|
||||||
|
-477 -826 -563 -975 -85 -148 -185 -322 -222 -385 -37 -63 -120 -207 -185
|
||||||
|
-320 -65 -113 -177 -306 -248 -430 -72 -124 -172 -297 -222 -385 -51 -88 -142
|
||||||
|
-245 -202 -350 -131 -226 -247 -427 -408 -705 -65 -113 -249 -432 -410 -710
|
||||||
|
-160 -278 -388 -673 -506 -877 -118 -205 -216 -373 -219 -373 -3 0 -52 82
|
||||||
|
-109 183 -58 100 -144 250 -192 332 -95 164 -402 696 -647 1120 -85 149 -228
|
||||||
|
396 -317 550 -212 365 -982 1700 -1008 1745 -10 19 -43 76 -72 125 -29 50 -64
|
||||||
|
110 -77 135 -14 25 -63 110 -110 190 -47 80 -96 165 -110 190 -14 25 -99 171
|
||||||
|
-188 325 -89 154 -174 300 -188 325 -13 25 -64 113 -112 195 -48 83 -140 242
|
||||||
|
-205 355 -65 113 -183 317 -263 454 -79 137 -152 264 -163 282 -50 89 -335
|
||||||
|
583 -354 614 -12 19 -34 58 -50 85 -15 28 -129 226 -253 440 -124 215 -235
|
||||||
|
408 -247 430 -12 22 -69 121 -127 220 -58 99 -226 389 -373 645 -148 256 -324
|
||||||
|
561 -392 678 -67 117 -134 232 -147 255 -13 23 -33 59 -46 80 l-22 37 -9615 0
|
||||||
|
-9615 0 20 -32z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 10 KiB |
@@ -0,0 +1,17 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||||
|
<title>UAA应用管理项目</title>
|
||||||
|
</head>
|
||||||
|
<body class="demo-project">
|
||||||
|
<noscript>
|
||||||
|
<strong>We're sorry but UAA应用管理项目 doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||||
|
</noscript>
|
||||||
|
<div id="app"></div>
|
||||||
|
<!-- built files will be auto injected -->
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
User-agent: *
|
||||||
|
Disallow:
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<router-view></router-view>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
watch: {
|
||||||
|
$route: {
|
||||||
|
handler (newValue) {
|
||||||
|
document.title = 'UAA应用管理项目';
|
||||||
|
if (newValue.meta && newValue.meta.title) document.title += ' - ' + newValue.meta.title;
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
export default class AuthClientDetailsController {
|
||||||
|
static list (sender, params, axiosOption, httpOption) {
|
||||||
|
return sender.doUrl('/admin/uaaadmin/authClientDetails/list', 'post', params, axiosOption, httpOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
static view (sender, params, axiosOption, httpOption) {
|
||||||
|
return sender.doUrl('/admin/uaaadmin/authClientDetails/view', 'get', params, axiosOption, httpOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
static export (sender, params, fileName) {
|
||||||
|
return sender.download('/admin/uaaadmin/authClientDetails/export', params, fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
static add (sender, params, axiosOption, httpOption) {
|
||||||
|
return sender.doUrl('/admin/uaaadmin/authClientDetails/add', 'post', params, axiosOption, httpOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
static update (sender, params, axiosOption, httpOption) {
|
||||||
|
return sender.doUrl('/admin/uaaadmin/authClientDetails/update', 'post', params, axiosOption, httpOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
static delete (sender, params, axiosOption, httpOption) {
|
||||||
|
return sender.doUrl('/admin/uaaadmin/authClientDetails/delete', 'post', params, axiosOption, httpOption);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import * as staticDict from '@/staticDict'
|
||||||
|
|
||||||
|
export default class DictionaryController {
|
||||||
|
static dictUserStatus () {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
resolve(staticDict.UserStatus);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
static dictUserType () {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
resolve(staticDict.UserType);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
export default class SysUaaOperatorController {
|
||||||
|
static list (sender, params, axiosOption, httpOption) {
|
||||||
|
return sender.doUrl('/admin/uaaadmin/sysUaaOperator/list', 'post', params, axiosOption, httpOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
static view (sender, params, axiosOption, httpOption) {
|
||||||
|
return sender.doUrl('/admin/uaaadmin/sysUaaOperator/view', 'get', params, axiosOption, httpOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
static export (sender, params, fileName) {
|
||||||
|
return sender.download('/admin/uaaadmin/sysUaaOperator/export', params, fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
static add (sender, params, axiosOption, httpOption) {
|
||||||
|
return sender.doUrl('/admin/uaaadmin/sysUaaOperator/add', 'post', params, axiosOption, httpOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
static update (sender, params, axiosOption, httpOption) {
|
||||||
|
return sender.doUrl('/admin/uaaadmin/sysUaaOperator/update', 'post', params, axiosOption, httpOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
static delete (sender, params, axiosOption, httpOption) {
|
||||||
|
return sender.doUrl('/admin/uaaadmin/sysUaaOperator/delete', 'post', params, axiosOption, httpOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
static resetPassword (sender, params, axiosOption, httpOption) {
|
||||||
|
return sender.doUrl('/admin/uaaadmin/sysUaaOperator/resetPassword', 'post', params, axiosOption, httpOption);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
export default class SysUaaUserController {
|
||||||
|
static list (sender, params, axiosOption, httpOption) {
|
||||||
|
return sender.doUrl('/admin/uaaadmin/sysUaaUser/list', 'post', params, axiosOption, httpOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
static view (sender, params, axiosOption, httpOption) {
|
||||||
|
return sender.doUrl('/admin/uaaadmin/sysUaaUser/view', 'get', params, axiosOption, httpOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
static export (sender, params, fileName) {
|
||||||
|
return sender.download('/admin/uaaadmin/sysUaaUser/export', params, fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
static add (sender, params, axiosOption, httpOption) {
|
||||||
|
return sender.doUrl('/admin/uaaadmin/sysUaaUser/add', 'post', params, axiosOption, httpOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
static update (sender, params, axiosOption, httpOption) {
|
||||||
|
return sender.doUrl('/admin/uaaadmin/sysUaaUser/update', 'post', params, axiosOption, httpOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
static delete (sender, params, axiosOption, httpOption) {
|
||||||
|
return sender.doUrl('/admin/uaaadmin/sysUaaUser/delete', 'post', params, axiosOption, httpOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
static resetPassword (sender, params, axiosOption, httpOption) {
|
||||||
|
return sender.doUrl('/admin/uaaadmin/sysUaaUser/resetPassword', 'post', params, axiosOption, httpOption);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
export default class SystemController {
|
||||||
|
static login (sender, params, axiosOption, httpOption) {
|
||||||
|
return sender.doUrl('admin/upms/login/doLogin', 'post', params, axiosOption, httpOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
static logout (sender, params, axiosOption, httpOption) {
|
||||||
|
return sender.doUrl('admin/upms/login/doLogout', 'post', params, axiosOption, httpOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
static changePassword (sender, params, axiosOption, httpOption) {
|
||||||
|
return sender.doUrl('admin/upms/login/changePassword', 'post', params, axiosOption, httpOption);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import SystemController from './Controller/SystemController'
|
||||||
|
import DictionaryController from './Controller/DictionaryController'
|
||||||
|
import AuthClientDetailsController from './Controller/AuthClientDetailsController.js'
|
||||||
|
import SysUaaUserController from './Controller/SysUaaUserController.js'
|
||||||
|
import SysUaaOperatorController from './Controller/SysUaaOperatorController.js'
|
||||||
|
|
||||||
|
export {
|
||||||
|
SystemController,
|
||||||
|
DictionaryController,
|
||||||
|
AuthClientDetailsController,
|
||||||
|
SysUaaUserController,
|
||||||
|
SysUaaOperatorController
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 899 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 11 KiB |
@@ -0,0 +1,593 @@
|
|||||||
|
@import "element-color.scss";
|
||||||
|
@import "transition.scss";
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
font-family: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;
|
||||||
|
background-color: rgb(228,240,255);
|
||||||
|
}
|
||||||
|
|
||||||
|
*,
|
||||||
|
*:before,
|
||||||
|
*:after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
$header-height: 60px;
|
||||||
|
|
||||||
|
// 过滤组件长度
|
||||||
|
$filter-item-width: 250px;
|
||||||
|
// 范围选择过滤组件长度
|
||||||
|
$filter-item-range-width: 400px;
|
||||||
|
// 左侧过滤树组件每一项高度
|
||||||
|
$tree-node-height: 40px;
|
||||||
|
// 高级管理表单标题高度
|
||||||
|
$advanced-title-height: 50px;
|
||||||
|
$border-color: rgb(216, 220, 229);
|
||||||
|
$menuHover: rgba(255,255,255,0.3);
|
||||||
|
$menu-background-color: transparent;
|
||||||
|
$tabs-header-margin-bottom: 25px;
|
||||||
|
$tab-header-background-color: #EBEEF5;
|
||||||
|
$image-item-width: 65px;
|
||||||
|
$box-padding-size: 25px;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 弹窗样式,封装的layer的弹窗
|
||||||
|
**/
|
||||||
|
body .layer-dialog .layui-layer-title{
|
||||||
|
border-radius: 4px 4px 0px 0px;
|
||||||
|
border:1px solid #01000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
body .layer-dialog .layui-layer-setwin {color: #ffffff}
|
||||||
|
|
||||||
|
body .layer-dialog {
|
||||||
|
border-radius: 4px;
|
||||||
|
border:1px solid #01000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
body .layer-dialog .layui-layer-content {
|
||||||
|
padding: $box-padding-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.demo-project {
|
||||||
|
.el-main {
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
.flex-box {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
.scrollbar_dropdown__wrap {
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-btn.el-button {
|
||||||
|
font-size: 18px;
|
||||||
|
padding: 5px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.default-padding-box {
|
||||||
|
padding: $box-padding-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
.padding-no-top {
|
||||||
|
padding: 0px $box-padding-size $box-padding-size $box-padding-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
.default-border {
|
||||||
|
border: 1px solid $border-color1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.default-border-left {
|
||||||
|
border-left: 1px solid $border-color1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.default-border-right {
|
||||||
|
border-right: 1px solid $border-color1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.default-border-top {
|
||||||
|
border-top: 1px solid $border-color1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.default-border-bottom {
|
||||||
|
border-bottom: 1px solid $border-color1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-close-box {
|
||||||
|
position: absolute;
|
||||||
|
background: #13ce66;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
height: 60px;
|
||||||
|
width: 60px;
|
||||||
|
right: -30px;
|
||||||
|
top:-30px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.el-button {
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
color: white;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤组件样式
|
||||||
|
**/
|
||||||
|
.mask-box {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0,0,0,0.5);
|
||||||
|
top: 0;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-box {
|
||||||
|
position: relative;
|
||||||
|
background-color: white;
|
||||||
|
padding: $box-padding-size $box-padding-size 0px $box-padding-size;
|
||||||
|
z-index: 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advance-filter-box {
|
||||||
|
padding-bottom: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-item {
|
||||||
|
width: $filter-item-width;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cascader-item {
|
||||||
|
width: 160px!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-range, .is-search {
|
||||||
|
width: $filter-item-range-width;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-operation-box {
|
||||||
|
align-self: flex-end;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 左侧树状组件的样式,用户高级管理表单以及用户管理表单
|
||||||
|
**/
|
||||||
|
.advanced-left-box {
|
||||||
|
border-right: 1px solid $border-color;
|
||||||
|
.el-tree-node__content {
|
||||||
|
height: $tree-node-height;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-node-item {
|
||||||
|
height: $tree-node-height;
|
||||||
|
line-height: $tree-node-height;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.tree-node-menu {
|
||||||
|
display: none;
|
||||||
|
float: right;
|
||||||
|
padding-right: 10px;
|
||||||
|
color: red!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover .tree-node-menu {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tree-node .el-button+.el-button {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* form表单输入组件宽度
|
||||||
|
**/
|
||||||
|
.full-width-input {
|
||||||
|
.el-select {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-cascader {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-date-editor {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-input-number {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 左侧菜单样式
|
||||||
|
**/
|
||||||
|
.sidebar-bg {
|
||||||
|
background: linear-gradient(#FC8051, #EB6265);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-title {
|
||||||
|
height: 160px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-title-text {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 18px;
|
||||||
|
color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
.el-menu {
|
||||||
|
background-color: $menu-background-color;
|
||||||
|
border-right-width: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-wrapper {
|
||||||
|
.el-menu {
|
||||||
|
background: linear-gradient(#FC8051, #EB6265);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-menu-item {
|
||||||
|
color: white;
|
||||||
|
i {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(255,255,255,0.3)!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-submenu {
|
||||||
|
.el-menu {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-submenu__title i {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-menu--collapse {
|
||||||
|
.el-submenu__icon-arrow {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nest-menu .el-submenu>.el-submenu__title, .el-submenu .el-menu-item {
|
||||||
|
min-width: 180px!important;
|
||||||
|
background: $menu-background-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-menu-item.is-active {
|
||||||
|
border-left: 3px solid #47ba5a;
|
||||||
|
background-color: rgba(255,255,255,0.3)!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-submenu__title {
|
||||||
|
background-color: $menu-background-color!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-menu {
|
||||||
|
border-right-width: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-collapse-btn {
|
||||||
|
padding: 0px;
|
||||||
|
width: 15px;
|
||||||
|
border-radius: 2px;
|
||||||
|
border: none;
|
||||||
|
height: 100px;
|
||||||
|
background-color: $--color-primary-light-5;
|
||||||
|
position: fixed;
|
||||||
|
top: 20%;
|
||||||
|
z-index: -1;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: $--color-primary-light-7;
|
||||||
|
}
|
||||||
|
.chart-border {
|
||||||
|
border: 1px solid #EBEEF5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多tab页表单,tab样式
|
||||||
|
**/
|
||||||
|
.el-tabs__header {
|
||||||
|
margin: 0 0 20px;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 表格表头背景色
|
||||||
|
**/
|
||||||
|
.table-header-gray, .has-gutter .gutter {
|
||||||
|
background-color: $tab-header-background-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图片上传以及显示样式
|
||||||
|
**/
|
||||||
|
.upload-image-item {
|
||||||
|
font-size: 28px;
|
||||||
|
color: #8c939d;
|
||||||
|
width: $image-item-width;
|
||||||
|
height: $image-item-width;
|
||||||
|
text-align: center;
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
.el-upload i {
|
||||||
|
line-height: $image-item-width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-image-multi {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-image-item .el-upload {
|
||||||
|
border: 1px dashed #d9d9d9;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.upload-image-item .el-upload:hover {
|
||||||
|
border-color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-image-show {
|
||||||
|
width: $image-item-width;
|
||||||
|
height: $image-item-width;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-cell-image {
|
||||||
|
width: $image-item-width;
|
||||||
|
height: $image-item-width;
|
||||||
|
line-height: $image-item-width;
|
||||||
|
text-align: center;
|
||||||
|
font-size: $image-item-width;
|
||||||
|
color: #606266;
|
||||||
|
margin: 0px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-image-list .el-upload-list__item {
|
||||||
|
width: $image-item-width;
|
||||||
|
height: $image-item-width;
|
||||||
|
line-height: $image-item-width;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-image-item .el-upload-list--picture-card .el-upload-list__item {
|
||||||
|
width: $image-item-width;
|
||||||
|
height: $image-item-width;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-image-item .el-upload.el-upload--text {
|
||||||
|
width: $image-item-width;
|
||||||
|
height: $image-item-width;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-image-item .el-upload--picture-card {
|
||||||
|
width: $image-item-width;
|
||||||
|
height: $image-item-width;
|
||||||
|
line-height: $image-item-width;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
$header-menu-height: 32px;
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
height: 100%;
|
||||||
|
background-color: #304156;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
height: $header-height;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header .menu-column {
|
||||||
|
margin-right: 20px;
|
||||||
|
.el-menu-item.is-active {
|
||||||
|
border-left: 0px solid #47ba5a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-menu {
|
||||||
|
float: right;
|
||||||
|
height: $header-menu-height;
|
||||||
|
line-height: $header-menu-height;
|
||||||
|
margin-top: ($header-height - $header-menu-height) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-img {
|
||||||
|
width: $header-menu-height;
|
||||||
|
height: $header-menu-height;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-left: 10px;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-dropdown {
|
||||||
|
color: $sub-text-color;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.user-dropdown-item {
|
||||||
|
font-size: 12px;
|
||||||
|
color: $main-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hamburger-container {
|
||||||
|
line-height: 70px;
|
||||||
|
height: $header-height;
|
||||||
|
float: left;
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-submenu__title {
|
||||||
|
background: #00000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 7px;
|
||||||
|
height: 7px;
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: #DDDEE0;
|
||||||
|
border-radius: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #A8A8A8;
|
||||||
|
}
|
||||||
|
.tree-select {
|
||||||
|
.el-tree-node__content {
|
||||||
|
height: 34px;
|
||||||
|
line-height: 34px;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-select.single-select-tree {
|
||||||
|
.el-tree-node.is-current > .el-tree-node__content > .el-tree-node__label {
|
||||||
|
color: $--color-primary;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell {
|
||||||
|
.operation-cell {
|
||||||
|
color: #006CDC;
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.single-select-tree {
|
||||||
|
min-width: 200px!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-card-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
height: 50px;
|
||||||
|
line-height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-card-operation {
|
||||||
|
flex-grow: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-card__header {
|
||||||
|
padding: 0px 15px;
|
||||||
|
}
|
||||||
|
.el-card__body {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-cascader {
|
||||||
|
width: 200px!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-scroll {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-scroll .el-scrollbar__view {
|
||||||
|
overflow-x: hidden!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-img-del {
|
||||||
|
position: absolute;
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
font-size: 16px;
|
||||||
|
top: 2px;
|
||||||
|
right: 2px;
|
||||||
|
color: #C0C4CC;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-img-del:hover {
|
||||||
|
color: #EF5E1C;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-label {
|
||||||
|
display: inline-block;
|
||||||
|
height: 29px;
|
||||||
|
line-height: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-progress {
|
||||||
|
height: 29px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-item {
|
||||||
|
width: 100%!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header-gray {
|
||||||
|
background: rgba(237,237,237,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 10px 0px;
|
||||||
|
line-height: 28px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml20 {
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mr20 {
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt20 {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb20 {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pl20 {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pr20 {
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pt20 {
|
||||||
|
padding-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pb20 {
|
||||||
|
padding-bottom: 20px;
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
$main-text-color: #303133;
|
||||||
|
$normal-text-color: #606266;
|
||||||
|
$sub-text-color: #909399;
|
||||||
|
$placeholder-text-color: #C0C4CC;
|
||||||
|
|
||||||
|
$border-color1: #DCDFE6;
|
||||||
|
$border-color2: #E4E7ED;
|
||||||
|
$border-color3: #EBEEF5;
|
||||||
|
$border-color4: #F2F6FC;
|
||||||
|
|
||||||
|
$success-color: #67C23A;
|
||||||
|
$warning-color: #E6A23C;
|
||||||
|
$danger-color: #F56C6C;
|
||||||
|
$info-color: #909399;
|
||||||
|
$--color-white: white;
|
||||||
|
$--color-primary: #EF5E1C !default;
|
||||||
|
$--color-primary-light-1: mix($--color-white, $--color-primary, 10%) !default; /* 53a8ff */
|
||||||
|
$--color-primary-light-2: mix($--color-white, $--color-primary, 20%) !default; /* 66b1ff */
|
||||||
|
$--color-primary-light-3: mix($--color-white, $--color-primary, 30%) !default; /* 79bbff */
|
||||||
|
$--color-primary-light-4: mix($--color-white, $--color-primary, 40%) !default; /* 8cc5ff */
|
||||||
|
$--color-primary-light-5: mix($--color-white, $--color-primary, 50%) !default; /* a0cfff */
|
||||||
|
$--color-primary-light-6: mix($--color-white, $--color-primary, 60%) !default; /* b3d8ff */
|
||||||
|
$--color-primary-light-7: mix($--color-white, $--color-primary, 70%) !default; /* c6e2ff */
|
||||||
|
$--color-primary-light-8: mix($--color-white, $--color-primary, 80%) !default; /* d9ecff */
|
||||||
|
$--color-primary-light-9: mix($--color-white, $--color-primary, 90%) !default; /* ecf5ff */
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
.form-advanced-manager {
|
||||||
|
.advance-filter-box {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 0px;
|
||||||
|
background-color: white;
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px $box-padding-size 15px $box-padding-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-box {
|
||||||
|
border-bottom: 1px solid $border-color;
|
||||||
|
padding: 0px 20px;
|
||||||
|
z-index: 20;
|
||||||
|
background-color: white;
|
||||||
|
height: $advanced-title-height;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
line-height: $advanced-title-height;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-box {
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
right: 10px;
|
||||||
|
height: $advanced-title-height;
|
||||||
|
|
||||||
|
.el-row {
|
||||||
|
margin: 10px 0px;
|
||||||
|
height: $advanced-title-height - 20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.advanced-right-box {
|
||||||
|
padding: 0px;
|
||||||
|
.gutter-box {
|
||||||
|
margin: (($advanced-title-height - 16)/2) 0px;
|
||||||
|
height: 16px;
|
||||||
|
width: 3px;
|
||||||
|
background-color: $--color-primary;
|
||||||
|
float: left
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-dict-manager {
|
||||||
|
.dict-title {
|
||||||
|
height: 50px;
|
||||||
|
line-height: 50px;
|
||||||
|
color: $main-text-color;
|
||||||
|
border-bottom: 1px solid $border-color1;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
span {
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dict-item {
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
color: #606266;
|
||||||
|
cursor: pointer;
|
||||||
|
padding-left: 20px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: $--color-primary-light-9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.active-dict-item {
|
||||||
|
border-left: 3px solid $--color-primary;
|
||||||
|
color: $--color-primary;
|
||||||
|
background-color: $--color-primary-light-9 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-scrollbar__bar.is-horizontal {
|
||||||
|
display: none!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.form-table-manager {
|
||||||
|
.advance-filter-box {
|
||||||
|
position: absolute;
|
||||||
|
padding: 20px;
|
||||||
|
top: 100%;
|
||||||
|
left: 0px;
|
||||||
|
background-color: white;
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px $box-padding-size 15px $box-padding-size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-table-multi-select {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-config {
|
||||||
|
padding: $box-padding-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-multi-fragment {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-single-fragment {
|
||||||
|
//
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
@import "../theme/index.css";
|
||||||
|
@import "base.scss";
|
||||||
|
@import "form-style.scss";
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*fade*/
|
||||||
|
.fade-enter-active,
|
||||||
|
.fade-leave-active {
|
||||||
|
transition: opacity 0.28s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-enter,
|
||||||
|
.fade-leave-active {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*fade*/
|
||||||
|
.breadcrumb-enter-active,
|
||||||
|
.breadcrumb-leave-active {
|
||||||
|
transition: all .5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb-enter,
|
||||||
|
.breadcrumb-leave-active {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(20px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb-move {
|
||||||
|
transition: all .5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb-leave-active {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,305 @@
|
|||||||
|
<template>
|
||||||
|
<div class="date-range">
|
||||||
|
<!--<year-range-panel />-->
|
||||||
|
<el-select v-model="dateType" :size="size"
|
||||||
|
style="max-width: 100px; min-width: 100px; margin-right: 10px;"
|
||||||
|
v-if="!hideTypeOnlyOne || validTypeList.length > 1">
|
||||||
|
<el-option v-for="type in validTypeList" :key="type.value" :value="type.value" :label="type.label" />
|
||||||
|
</el-select>
|
||||||
|
<el-date-picker style="flex-grow: 1;" v-model="currentDates"
|
||||||
|
:size="size" :placeholder="placeholder" :type="innerDateType"
|
||||||
|
:disabled="disabled" :format="innerDateFormat" :readonly="readonly" :editable="editable"
|
||||||
|
:clearable="clearable" :start-placeholder="startPlaceholder" :end-placeholder="endPlaceholder"
|
||||||
|
:align="align" :range-separator="rangeSeparator" :value-format="valueFormat"
|
||||||
|
:prefix-icon="prefixIcon" :clear-icon="clearIcon" @change="onValueChange" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { formatDate, parseDate } from 'element-ui/src/utils/date-util';
|
||||||
|
|
||||||
|
const allTypeList = [{
|
||||||
|
value: 'day',
|
||||||
|
label: '自然日'
|
||||||
|
}, {
|
||||||
|
value: 'month',
|
||||||
|
label: '自然月'
|
||||||
|
}, {
|
||||||
|
value: 'year',
|
||||||
|
label: '自然年'
|
||||||
|
}];
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'DateRange',
|
||||||
|
props: {
|
||||||
|
/**
|
||||||
|
* 绑定的数据
|
||||||
|
*/
|
||||||
|
value: {
|
||||||
|
type: [Array],
|
||||||
|
default: () => {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 默认显示的数据选择方式,如果不存在与allowTypes中则显示allowTypes中的第一个
|
||||||
|
*/
|
||||||
|
defaultDateType: {
|
||||||
|
type: String,
|
||||||
|
default: 'day'
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 组件大小(medium / small / mini)
|
||||||
|
*/
|
||||||
|
size: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 数据选择方式只有一个的时候是否隐藏数据选择方式下拉
|
||||||
|
*/
|
||||||
|
hideTypeOnlyOne: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 允许的数据选择方式(day, month, year)
|
||||||
|
* 默认值['day', 'month', 'year']
|
||||||
|
*/
|
||||||
|
allowTypes: {
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return allTypeList.map((item) => {
|
||||||
|
return item.value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 是否范围选择
|
||||||
|
*/
|
||||||
|
isRange: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 输出字符串的format
|
||||||
|
*/
|
||||||
|
outputFormat: {
|
||||||
|
type: String,
|
||||||
|
default: 'yyyy-MM-dd HH:mm:ss'
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 非范围选择时的占位内容
|
||||||
|
*/
|
||||||
|
placeholder: String,
|
||||||
|
/**
|
||||||
|
* 范围选择时开始日期的占位内容
|
||||||
|
*/
|
||||||
|
startPlaceholder: String,
|
||||||
|
/**
|
||||||
|
* 范围选择时结束日期的占位内容
|
||||||
|
*/
|
||||||
|
endPlaceholder: String,
|
||||||
|
/**
|
||||||
|
* 完全只读
|
||||||
|
*/
|
||||||
|
readonly: Boolean,
|
||||||
|
/**
|
||||||
|
* 禁用
|
||||||
|
*/
|
||||||
|
disabled: Boolean,
|
||||||
|
/**
|
||||||
|
* 文本框可输入
|
||||||
|
*/
|
||||||
|
editable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 是否显示清除按钮
|
||||||
|
*/
|
||||||
|
clearable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 对齐方式(left, center, right)
|
||||||
|
*/
|
||||||
|
align: {
|
||||||
|
type: String,
|
||||||
|
default: 'left'
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 选择范围时的分隔符
|
||||||
|
*/
|
||||||
|
rangeSeparator: {
|
||||||
|
type: String,
|
||||||
|
default: '-'
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 可选,绑定值的格式。不指定则绑定值为 Date 对象
|
||||||
|
*/
|
||||||
|
valueFormat: {
|
||||||
|
type: String,
|
||||||
|
default: 'yyyy-MM-dd'
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 自定义头部图标的类名
|
||||||
|
*/
|
||||||
|
prefixIcon: {
|
||||||
|
type: String,
|
||||||
|
default: 'el-icon-date'
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 自定义清空图标的类名
|
||||||
|
*/
|
||||||
|
clearIcon: {
|
||||||
|
type: String,
|
||||||
|
default: 'el-icon-circle-close'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
dateType: this.defaultDateType,
|
||||||
|
currentDates: undefined
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onValueChange (values) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.emitChange();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
emitChange () {
|
||||||
|
let outputDate = [];
|
||||||
|
if (this.currentDates != null) {
|
||||||
|
if (!this.isRange) {
|
||||||
|
outputDate[0] = new Date(this.currentDates);
|
||||||
|
outputDate[1] = new Date(this.currentDates);
|
||||||
|
} else {
|
||||||
|
if (Array.isArray(this.currentDates) && this.currentDates.length === 2) {
|
||||||
|
outputDate[0] = new Date(this.currentDates[0]);
|
||||||
|
outputDate[1] = new Date(this.currentDates[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outputDate[0] != null && outputDate[1] != null) {
|
||||||
|
outputDate[0].setHours(0, 0, 0, 0);
|
||||||
|
outputDate[1].setHours(0, 0, 0, 0);
|
||||||
|
switch (this.dateType) {
|
||||||
|
case 'day':
|
||||||
|
outputDate[1].setDate(outputDate[1].getDate() + 1);
|
||||||
|
break;
|
||||||
|
case 'month':
|
||||||
|
outputDate[1].setDate(1);
|
||||||
|
outputDate[0].setDate(1);
|
||||||
|
outputDate[1].setMonth(outputDate[1].getMonth() + 1);
|
||||||
|
break;
|
||||||
|
case 'year':
|
||||||
|
outputDate[1].setMonth(0);
|
||||||
|
outputDate[1].setDate(1);
|
||||||
|
outputDate[0].setMonth(0);
|
||||||
|
outputDate[0].setDate(1);
|
||||||
|
outputDate[1].setFullYear(outputDate[1].getFullYear() + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
outputDate[1] = new Date(outputDate[1].getTime() - 1);
|
||||||
|
|
||||||
|
outputDate[0] = formatDate(outputDate[0], this.outputFormat);
|
||||||
|
outputDate[1] = formatDate(outputDate[1], this.outputFormat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.$emit('input', outputDate);
|
||||||
|
this.$emit('change', outputDate);
|
||||||
|
},
|
||||||
|
getCurrentStatsDateType () {
|
||||||
|
return this.dateType;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
validTypeList () {
|
||||||
|
return allTypeList.filter((item) => {
|
||||||
|
return this.allowTypes.indexOf(item.value) !== -1;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* el-date-picker使用的type
|
||||||
|
*/
|
||||||
|
innerDateType () {
|
||||||
|
switch (this.dateType) {
|
||||||
|
case 'day': return this.isRange ? 'daterange' : 'date';
|
||||||
|
case 'month': return this.isRange ? 'monthrange' : 'month';
|
||||||
|
case 'year': return this.isRange ? 'monthrange' : 'year';
|
||||||
|
default: return this.isRange ? 'daterange' : 'date';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* el-date-picker使用的format
|
||||||
|
*/
|
||||||
|
innerDateFormat () {
|
||||||
|
switch (this.dateType) {
|
||||||
|
case 'day': return 'yyyy-MM-dd';
|
||||||
|
case 'month': return 'yyyy-MM';
|
||||||
|
case 'year': return 'yyyy';
|
||||||
|
default: return 'yyyy-MM-dd';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value: {
|
||||||
|
handler: function (newValue, oldValue) {
|
||||||
|
if (newValue == null || newValue.length < 2) {
|
||||||
|
this.currentDates = this.isRange ? [] : undefined;
|
||||||
|
} else {
|
||||||
|
if (this.currentDates == null) this.currentDates = [];
|
||||||
|
if (this.isRange) {
|
||||||
|
this.currentDates = [
|
||||||
|
parseDate(newValue[0], this.valueFormat),
|
||||||
|
parseDate(newValue[1], this.valueFormat)
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
this.currentDates = parseDate(newValue[0], this.valueFormat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true,
|
||||||
|
deep: true
|
||||||
|
},
|
||||||
|
dateType: {
|
||||||
|
handler: function (newValue, oldValue) {
|
||||||
|
if (this.allowTypes.indexOf(this.dateType) === -1) {
|
||||||
|
this.dateType = this.allowTypes[0] || 'day';
|
||||||
|
}
|
||||||
|
this.emitChange();
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
},
|
||||||
|
defaultDateType: {
|
||||||
|
handler: function (newValue, oldValue) {
|
||||||
|
if (this.allowTypes.indexOf(newValue) !== -1) {
|
||||||
|
this.dateType = newValue;
|
||||||
|
} else {
|
||||||
|
this.dateType = this.allowTypes[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isRange: {
|
||||||
|
handler: function (newValue, oldValue) {
|
||||||
|
let temp;
|
||||||
|
if (newValue) {
|
||||||
|
temp = [this.currentDates, this.currentDates];
|
||||||
|
} else {
|
||||||
|
temp = this.currentDates[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentDates = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.date-range {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
import Vue from 'vue';
|
||||||
|
import router from '@/router';
|
||||||
|
import store from '@/store';
|
||||||
|
|
||||||
|
window.jQuery = $;
|
||||||
|
const layer = require('layui-layer');
|
||||||
|
|
||||||
|
class Dialog {
|
||||||
|
/**
|
||||||
|
* 关闭弹窗
|
||||||
|
* @param {*} index 要关闭的弹窗的index
|
||||||
|
*/
|
||||||
|
static close (index) {
|
||||||
|
layer.close(index);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 关闭所有弹窗
|
||||||
|
*/
|
||||||
|
static closeAll () {
|
||||||
|
layer.closeAll();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 打开弹窗
|
||||||
|
* @param {*} title 弹窗标题
|
||||||
|
* @param {*} component 弹窗内容的组件
|
||||||
|
* @param {*} options 弹窗设置(详情请见layui官网)
|
||||||
|
* @param {*} params 弹窗组件参数
|
||||||
|
*/
|
||||||
|
static show (title, component, options, params) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let layerOptions = {
|
||||||
|
title: title,
|
||||||
|
type: 1,
|
||||||
|
skin: 'layer-dialog',
|
||||||
|
resize: false,
|
||||||
|
offset: 'auto',
|
||||||
|
zIndex: 1000,
|
||||||
|
index: 0,
|
||||||
|
contentDom: null
|
||||||
|
};
|
||||||
|
|
||||||
|
layerOptions = {...layerOptions, ...options};
|
||||||
|
layerOptions.end = () => {
|
||||||
|
if (layerOptions.contentDom) document.body.removeChild(layerOptions.contentDom);
|
||||||
|
}
|
||||||
|
|
||||||
|
let observer = {
|
||||||
|
cancel: function (isSuccess = false) {
|
||||||
|
layer.close(this.index);
|
||||||
|
if (isSuccess) {
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
index: -1
|
||||||
|
}
|
||||||
|
layerOptions.cancel = () => {
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
let dom = document.createElement('div');
|
||||||
|
document.body.appendChild(dom);
|
||||||
|
let Content = Vue.extend(component);
|
||||||
|
let vueObj = new Content({router: router, store: store, propsData: params});
|
||||||
|
vueObj.observer = observer;
|
||||||
|
vueObj.$mount(dom);
|
||||||
|
layerOptions.contentDom = vueObj.$el;
|
||||||
|
layerOptions.content = $(layerOptions.contentDom);
|
||||||
|
observer.index = layer.open(layerOptions);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vue.prototype.$dialog = Dialog;
|
||||||
|
|
||||||
|
export default Dialog;
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
<template>
|
||||||
|
<el-row class="flex-box" type="flex" :justify="rowJustify">
|
||||||
|
<slot />
|
||||||
|
<div v-for="item in tempDomCount" :key="item" :style="{width: tempDomWidth}" />
|
||||||
|
<el-row type="flex" :justify="operatorPosition" :style="getMenuBoxStyle">
|
||||||
|
<slot name="operator" />
|
||||||
|
</el-row>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'FilterBox',
|
||||||
|
props: {
|
||||||
|
/**
|
||||||
|
* 每一个过滤项宽度(包含标题和输入框宽度总和)
|
||||||
|
*/
|
||||||
|
itemWidth: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 每一项下间距
|
||||||
|
*/
|
||||||
|
marginBottom: {
|
||||||
|
type: String,
|
||||||
|
default: '18px'
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 按钮块最小宽度默认350,当每一行剩余空间大于此值,按钮块将不会折行
|
||||||
|
*/
|
||||||
|
minMenuWidth: {
|
||||||
|
type: Number,
|
||||||
|
default: 350
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 按钮位置,默认为end,可选值为start/end/center/space-around/space-between
|
||||||
|
*/
|
||||||
|
operatorPosition: {
|
||||||
|
type: String,
|
||||||
|
default: 'end'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
tempDomCount: 0,
|
||||||
|
tempDomWidth: undefined,
|
||||||
|
operatorWidth: undefined,
|
||||||
|
oldFilterItemCount: 0,
|
||||||
|
oldHasOperator: false,
|
||||||
|
oldWidth: 0,
|
||||||
|
rowJustify: 'space-between'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
getMenuBoxStyle () {
|
||||||
|
return {
|
||||||
|
'width': this.operatorWidth,
|
||||||
|
'margin-bottom': this.marginBottom,
|
||||||
|
'flex-grow': this.operatorWidth ? undefined : '1'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onUpdate () {
|
||||||
|
setTimeout(() => {
|
||||||
|
let filterItemCount = Array.isArray(this.$slots.default) ? this.$slots.default.filter(item => item.context).length : 0;
|
||||||
|
let hasOperator = Array.isArray(this.$slots.operator) && this.$slots.operator.length > 0;
|
||||||
|
let width = $(this.$el).width();
|
||||||
|
if (filterItemCount === this.oldFilterItemCount && hasOperator === this.oldHasOperator && width === this.oldWidth) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let lineCount = this.itemWidth > 0 ? parseInt(width / this.itemWidth) : 1;
|
||||||
|
lineCount = Math.max(1, lineCount);
|
||||||
|
let residueCount = filterItemCount % lineCount;
|
||||||
|
|
||||||
|
this.tempDomCount = 0;
|
||||||
|
this.tempDomWidth = undefined;
|
||||||
|
this.rowJustify = 'space-between';
|
||||||
|
let tempCount = residueCount === 0 ? 0 : (lineCount - residueCount);
|
||||||
|
if (hasOperator) {
|
||||||
|
let residueWidth = width - ((Math.min(lineCount, filterItemCount) - residueCount) * this.itemWidth) - ((tempCount >= 1) ? 20 : 0);
|
||||||
|
// 判断剩余的空间是否够放下操作按钮
|
||||||
|
if (residueWidth >= this.minMenuWidth && residueCount === 0) {
|
||||||
|
this.rowJustify = 'start';
|
||||||
|
this.operatorWidth = undefined;
|
||||||
|
} else {
|
||||||
|
// 剩余空位数大于1,需要占位dom
|
||||||
|
if (tempCount >= 1) {
|
||||||
|
if (residueWidth >= this.minMenuWidth) {
|
||||||
|
this.tempDomCount = tempCount - 1;
|
||||||
|
this.tempDomWidth = this.tempDomCount > 0 ? (20 / this.tempDomCount) + 'px' : undefined;
|
||||||
|
this.operatorWidth = this.tempDomCount > 0 ? (((tempCount * this.itemWidth) - 20) + 'px') : (this.itemWidth + 'px');
|
||||||
|
} else {
|
||||||
|
this.tempDomCount = tempCount;
|
||||||
|
this.tempDomWidth = (residueWidth / this.tempDomCount) + 'px';
|
||||||
|
this.operatorWidth = '100%';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.operatorWidth = '100%';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.tempDomCount = tempCount;
|
||||||
|
this.tempDomWidth = this.itemWidth + 'px';
|
||||||
|
}
|
||||||
|
|
||||||
|
this.oldFilterItemCount = filterItemCount;
|
||||||
|
this.oldHasOperator = hasOperator;
|
||||||
|
this.oldWidth = width;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeUpdate () {
|
||||||
|
this.onUpdate();
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.onUpdate();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
window.addEventListener('resize', this.onUpdate);
|
||||||
|
},
|
||||||
|
beforeDestroy () {
|
||||||
|
window.removeEventListener('resize', this.onUpdate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<svg t="1492500959545" @click="toggleClick" class="hamburger" :class="{'is-active':isActive}" style="" viewBox="0 0 1024 1024"
|
||||||
|
version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1691" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64">
|
||||||
|
<path d="M966.8023 568.849776 57.196677 568.849776c-31.397081 0-56.850799-25.452695-56.850799-56.850799l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 543.397081 998.200404 568.849776 966.8023 568.849776z"
|
||||||
|
p-id="1692"></path>
|
||||||
|
<path d="M966.8023 881.527125 57.196677 881.527125c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 856.07443 998.200404 881.527125 966.8023 881.527125z"
|
||||||
|
p-id="1693"></path>
|
||||||
|
<path d="M966.8023 256.17345 57.196677 256.17345c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.850799 56.850799-56.850799l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.850799l0 0C1023.653099 230.720755 998.200404 256.17345 966.8023 256.17345z"
|
||||||
|
p-id="1694"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'hamburger',
|
||||||
|
props: {
|
||||||
|
isActive: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
toggleClick: {
|
||||||
|
type: Function,
|
||||||
|
default: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.hamburger {
|
||||||
|
display: inline-block;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
transform: rotate(90deg);
|
||||||
|
transform-origin: 50% 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hamburger.is-active {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,280 @@
|
|||||||
|
[
|
||||||
|
"el-icon-delete-solid",
|
||||||
|
"el-icon-delete",
|
||||||
|
"el-icon-s-tools",
|
||||||
|
"el-icon-setting",
|
||||||
|
"el-icon-user-solid",
|
||||||
|
"el-icon-user",
|
||||||
|
"el-icon-phone",
|
||||||
|
"el-icon-phone-outline",
|
||||||
|
"el-icon-more",
|
||||||
|
"el-icon-more-outline",
|
||||||
|
"el-icon-star-on",
|
||||||
|
"el-icon-star-off",
|
||||||
|
"el-icon-s-goods",
|
||||||
|
"el-icon-goods",
|
||||||
|
"el-icon-warning",
|
||||||
|
"el-icon-warning-outline",
|
||||||
|
"el-icon-question",
|
||||||
|
"el-icon-info",
|
||||||
|
"el-icon-remove",
|
||||||
|
"el-icon-circle-plus",
|
||||||
|
"el-icon-success",
|
||||||
|
"el-icon-error",
|
||||||
|
"el-icon-zoom-in",
|
||||||
|
"el-icon-zoom-out",
|
||||||
|
"el-icon-remove-outline",
|
||||||
|
"el-icon-circle-plus-outline",
|
||||||
|
"el-icon-circle-check",
|
||||||
|
"el-icon-circle-close",
|
||||||
|
"el-icon-s-help",
|
||||||
|
"el-icon-help",
|
||||||
|
"el-icon-minus",
|
||||||
|
"el-icon-plus",
|
||||||
|
"el-icon-check",
|
||||||
|
"el-icon-close",
|
||||||
|
"el-icon-picture",
|
||||||
|
"el-icon-picture-outline",
|
||||||
|
"el-icon-picture-outline-round",
|
||||||
|
"el-icon-upload",
|
||||||
|
"el-icon-upload2",
|
||||||
|
"el-icon-download",
|
||||||
|
"el-icon-camera-solid",
|
||||||
|
"el-icon-camera",
|
||||||
|
"el-icon-video-camera-solid",
|
||||||
|
"el-icon-video-camera",
|
||||||
|
"el-icon-message-solid",
|
||||||
|
"el-icon-bell",
|
||||||
|
"el-icon-s-cooperation",
|
||||||
|
"el-icon-s-order",
|
||||||
|
"el-icon-s-platform",
|
||||||
|
"el-icon-s-fold",
|
||||||
|
"el-icon-s-unfold",
|
||||||
|
"el-icon-s-operation",
|
||||||
|
"el-icon-s-promotion",
|
||||||
|
"el-icon-s-home",
|
||||||
|
"el-icon-s-release",
|
||||||
|
"el-icon-s-ticket",
|
||||||
|
"el-icon-s-management",
|
||||||
|
"el-icon-s-open",
|
||||||
|
"el-icon-s-shop",
|
||||||
|
"el-icon-s-marketing",
|
||||||
|
"el-icon-s-flag",
|
||||||
|
"el-icon-s-comment",
|
||||||
|
"el-icon-s-finance",
|
||||||
|
"el-icon-s-claim",
|
||||||
|
"el-icon-s-custom",
|
||||||
|
"el-icon-s-opportunity",
|
||||||
|
"el-icon-s-data",
|
||||||
|
"el-icon-s-check",
|
||||||
|
"el-icon-s-grid",
|
||||||
|
"el-icon-menu",
|
||||||
|
"el-icon-share",
|
||||||
|
"el-icon-d-caret",
|
||||||
|
"el-icon-caret-left",
|
||||||
|
"el-icon-caret-right",
|
||||||
|
"el-icon-caret-bottom",
|
||||||
|
"el-icon-caret-top",
|
||||||
|
"el-icon-bottom-left",
|
||||||
|
"el-icon-bottom-right",
|
||||||
|
"el-icon-back",
|
||||||
|
"el-icon-right",
|
||||||
|
"el-icon-bottom",
|
||||||
|
"el-icon-top",
|
||||||
|
"el-icon-top-left",
|
||||||
|
"el-icon-top-right",
|
||||||
|
"el-icon-arrow-left",
|
||||||
|
"el-icon-arrow-right",
|
||||||
|
"el-icon-arrow-down",
|
||||||
|
"el-icon-arrow-up",
|
||||||
|
"el-icon-d-arrow-left",
|
||||||
|
"el-icon-d-arrow-right",
|
||||||
|
"el-icon-video-pause",
|
||||||
|
"el-icon-video-play",
|
||||||
|
"el-icon-refresh",
|
||||||
|
"el-icon-refresh-right",
|
||||||
|
"el-icon-refresh-left",
|
||||||
|
"el-icon-finished",
|
||||||
|
"el-icon-sort",
|
||||||
|
"el-icon-sort-up",
|
||||||
|
"el-icon-sort-down",
|
||||||
|
"el-icon-rank",
|
||||||
|
"el-icon-loading",
|
||||||
|
"el-icon-view",
|
||||||
|
"el-icon-c-scale-to-original",
|
||||||
|
"el-icon-date",
|
||||||
|
"el-icon-edit",
|
||||||
|
"el-icon-edit-outline",
|
||||||
|
"el-icon-folder",
|
||||||
|
"el-icon-folder-opened",
|
||||||
|
"el-icon-folder-add",
|
||||||
|
"el-icon-folder-remove",
|
||||||
|
"el-icon-folder-delete",
|
||||||
|
"el-icon-folder-checked",
|
||||||
|
"el-icon-tickets",
|
||||||
|
"el-icon-document-remove",
|
||||||
|
"el-icon-document-delete",
|
||||||
|
"el-icon-document-copy",
|
||||||
|
"el-icon-document-checked",
|
||||||
|
"el-icon-document",
|
||||||
|
"el-icon-document-add",
|
||||||
|
"el-icon-printer",
|
||||||
|
"el-icon-paperclip",
|
||||||
|
"el-icon-takeaway-box",
|
||||||
|
"el-icon-search",
|
||||||
|
"el-icon-monitor",
|
||||||
|
"el-icon-attract",
|
||||||
|
"el-icon-mobile",
|
||||||
|
"el-icon-scissors",
|
||||||
|
"el-icon-umbrella",
|
||||||
|
"el-icon-headset",
|
||||||
|
"el-icon-brush",
|
||||||
|
"el-icon-mouse",
|
||||||
|
"el-icon-coordinate",
|
||||||
|
"el-icon-magic-stick",
|
||||||
|
"el-icon-reading",
|
||||||
|
"el-icon-data-line",
|
||||||
|
"el-icon-data-board",
|
||||||
|
"el-icon-pie-chart",
|
||||||
|
"el-icon-data-analysis",
|
||||||
|
"el-icon-collection-tag",
|
||||||
|
"el-icon-film",
|
||||||
|
"el-icon-suitcase",
|
||||||
|
"el-icon-suitcase-1",
|
||||||
|
"el-icon-receiving",
|
||||||
|
"el-icon-collection",
|
||||||
|
"el-icon-files",
|
||||||
|
"el-icon-notebook-1",
|
||||||
|
"el-icon-notebook-2",
|
||||||
|
"el-icon-toilet-paper",
|
||||||
|
"el-icon-office-building",
|
||||||
|
"el-icon-school",
|
||||||
|
"el-icon-table-lamp",
|
||||||
|
"el-icon-house",
|
||||||
|
"el-icon-no-smoking",
|
||||||
|
"el-icon-smoking",
|
||||||
|
"el-icon-shopping-cart-full",
|
||||||
|
"el-icon-shopping-cart-1",
|
||||||
|
"el-icon-shopping-cart-2",
|
||||||
|
"el-icon-shopping-bag-1",
|
||||||
|
"el-icon-shopping-bag-2",
|
||||||
|
"el-icon-sold-out",
|
||||||
|
"el-icon-sell",
|
||||||
|
"el-icon-present",
|
||||||
|
"el-icon-box",
|
||||||
|
"el-icon-bank-card",
|
||||||
|
"el-icon-money",
|
||||||
|
"el-icon-coin",
|
||||||
|
"el-icon-wallet",
|
||||||
|
"el-icon-discount",
|
||||||
|
"el-icon-price-tag",
|
||||||
|
"el-icon-news",
|
||||||
|
"el-icon-guide",
|
||||||
|
"el-icon-male",
|
||||||
|
"el-icon-female",
|
||||||
|
"el-icon-thumb",
|
||||||
|
"el-icon-cpu",
|
||||||
|
"el-icon-link",
|
||||||
|
"el-icon-connection",
|
||||||
|
"el-icon-open",
|
||||||
|
"el-icon-turn-off",
|
||||||
|
"el-icon-set-up",
|
||||||
|
"el-icon-chat-round",
|
||||||
|
"el-icon-chat-line-round",
|
||||||
|
"el-icon-chat-square",
|
||||||
|
"el-icon-chat-dot-round",
|
||||||
|
"el-icon-chat-dot-square",
|
||||||
|
"el-icon-chat-line-square",
|
||||||
|
"el-icon-message",
|
||||||
|
"el-icon-postcard",
|
||||||
|
"el-icon-position",
|
||||||
|
"el-icon-turn-off-microphone",
|
||||||
|
"el-icon-microphone",
|
||||||
|
"el-icon-close-notification",
|
||||||
|
"el-icon-bangzhu",
|
||||||
|
"el-icon-time",
|
||||||
|
"el-icon-odometer",
|
||||||
|
"el-icon-crop",
|
||||||
|
"el-icon-aim",
|
||||||
|
"el-icon-switch-button",
|
||||||
|
"el-icon-full-screen",
|
||||||
|
"el-icon-copy-document",
|
||||||
|
"el-icon-mic",
|
||||||
|
"el-icon-stopwatch",
|
||||||
|
"el-icon-medal-1",
|
||||||
|
"el-icon-medal",
|
||||||
|
"el-icon-trophy",
|
||||||
|
"el-icon-trophy-1",
|
||||||
|
"el-icon-first-aid-kit",
|
||||||
|
"el-icon-discover",
|
||||||
|
"el-icon-place",
|
||||||
|
"el-icon-location",
|
||||||
|
"el-icon-location-outline",
|
||||||
|
"el-icon-location-information",
|
||||||
|
"el-icon-add-location",
|
||||||
|
"el-icon-delete-location",
|
||||||
|
"el-icon-map-location",
|
||||||
|
"el-icon-alarm-clock",
|
||||||
|
"el-icon-timer",
|
||||||
|
"el-icon-watch-1",
|
||||||
|
"el-icon-watch",
|
||||||
|
"el-icon-lock",
|
||||||
|
"el-icon-unlock",
|
||||||
|
"el-icon-key",
|
||||||
|
"el-icon-service",
|
||||||
|
"el-icon-mobile-phone",
|
||||||
|
"el-icon-bicycle",
|
||||||
|
"el-icon-truck",
|
||||||
|
"el-icon-ship",
|
||||||
|
"el-icon-basketball",
|
||||||
|
"el-icon-football",
|
||||||
|
"el-icon-soccer",
|
||||||
|
"el-icon-baseball",
|
||||||
|
"el-icon-wind-power",
|
||||||
|
"el-icon-light-rain",
|
||||||
|
"el-icon-lightning",
|
||||||
|
"el-icon-heavy-rain",
|
||||||
|
"el-icon-sunrise",
|
||||||
|
"el-icon-sunrise-1",
|
||||||
|
"el-icon-sunset",
|
||||||
|
"el-icon-sunny",
|
||||||
|
"el-icon-cloudy",
|
||||||
|
"el-icon-partly-cloudy",
|
||||||
|
"el-icon-cloudy-and-sunny",
|
||||||
|
"el-icon-moon",
|
||||||
|
"el-icon-moon-night",
|
||||||
|
"el-icon-dish",
|
||||||
|
"el-icon-dish-1",
|
||||||
|
"el-icon-food",
|
||||||
|
"el-icon-chicken",
|
||||||
|
"el-icon-fork-spoon",
|
||||||
|
"el-icon-knife-fork",
|
||||||
|
"el-icon-burger",
|
||||||
|
"el-icon-tableware",
|
||||||
|
"el-icon-sugar",
|
||||||
|
"el-icon-dessert",
|
||||||
|
"el-icon-ice-cream",
|
||||||
|
"el-icon-hot-water",
|
||||||
|
"el-icon-water-cup",
|
||||||
|
"el-icon-coffee-cup",
|
||||||
|
"el-icon-cold-drink",
|
||||||
|
"el-icon-goblet",
|
||||||
|
"el-icon-goblet-full",
|
||||||
|
"el-icon-goblet-square",
|
||||||
|
"el-icon-goblet-square-full",
|
||||||
|
"el-icon-refrigerator",
|
||||||
|
"el-icon-grape",
|
||||||
|
"el-icon-watermelon",
|
||||||
|
"el-icon-cherry",
|
||||||
|
"el-icon-apple",
|
||||||
|
"el-icon-pear",
|
||||||
|
"el-icon-orange",
|
||||||
|
"el-icon-coffee",
|
||||||
|
"el-icon-ice-tea",
|
||||||
|
"el-icon-ice-drink",
|
||||||
|
"el-icon-milk-tea",
|
||||||
|
"el-icon-potato-strips",
|
||||||
|
"el-icon-lollipop",
|
||||||
|
"el-icon-ice-cream-square",
|
||||||
|
"el-icon-ice-cream-round"
|
||||||
|
]
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
<template>
|
||||||
|
<el-popover width="510" v-model="showDropdown" @show="onDropdownShow">
|
||||||
|
<div class="icon-select-dropdown">
|
||||||
|
<el-row type="flex" style="flex-wrap: wrap">
|
||||||
|
<el-col :span="3" v-for="icon in getIconList" :key="icon" class="icon-item"
|
||||||
|
:class="{active: (value === icon)}" @click.native="onIconClick(icon)">
|
||||||
|
<i :class="icon" />
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row type="flex" justify="space-between">
|
||||||
|
<el-button type="text" @click="onClearClick" style="margin-left: 10px;">清空</el-button>
|
||||||
|
<el-pagination
|
||||||
|
:current-page.sync="currentPage"
|
||||||
|
:page-size="pageSize"
|
||||||
|
layout="prev, pager, next"
|
||||||
|
:total="getIconCount">
|
||||||
|
</el-pagination>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
<div slot="reference" class="icon-select"
|
||||||
|
:style="{width: height + 'px', height: height + 'px', 'line-height': height + 'px', 'font-size': height * 0.5 + 'px'}">
|
||||||
|
<i :class="value" />
|
||||||
|
</div>
|
||||||
|
</el-popover>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import iconList from './icon.json';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
/**
|
||||||
|
* 绑定字段
|
||||||
|
*/
|
||||||
|
value: String,
|
||||||
|
/**
|
||||||
|
* 组件高度,单位px
|
||||||
|
*/
|
||||||
|
height: {
|
||||||
|
type: Number,
|
||||||
|
default: 45
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
showDropdown: false,
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 32
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onIconClick (icon) {
|
||||||
|
this.$emit('input', icon);
|
||||||
|
this.showDropdown = false;
|
||||||
|
},
|
||||||
|
onClearClick () {
|
||||||
|
this.$emit('input');
|
||||||
|
this.showDropdown = false;
|
||||||
|
},
|
||||||
|
onDropdownShow () {
|
||||||
|
this.currentPage = 1
|
||||||
|
let pos = iconList.indexOf(this.value);
|
||||||
|
if (pos >= 0) {
|
||||||
|
this.currentPage += Math.floor(pos / this.pageSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
getIconCount () {
|
||||||
|
return iconList.length;
|
||||||
|
},
|
||||||
|
getIconList () {
|
||||||
|
let beginPos = (this.currentPage - 1) * this.pageSize;
|
||||||
|
let endPos = beginPos + this.pageSize;
|
||||||
|
return iconList.slice(beginPos, endPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.icon-select {
|
||||||
|
text-align: center;
|
||||||
|
color: #5F6266;
|
||||||
|
border: 1px solid #DCDFE6;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.icon-item {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 20px;
|
||||||
|
color: #5F6266;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 1px solid #DCDFE6;
|
||||||
|
margin: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.active {
|
||||||
|
color: #EF5E1C;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,226 @@
|
|||||||
|
<template>
|
||||||
|
<div class="el-input el-date-editor el-range-editor el-input__inner el-input-number-range"
|
||||||
|
:class="
|
||||||
|
[
|
||||||
|
inputSize ? 'el-range-editor--' + inputSize : '',
|
||||||
|
focused ? 'is-active' : '',
|
||||||
|
{
|
||||||
|
'is-disabled': inputDisabled,
|
||||||
|
'el-input--prefix': prefixIcon
|
||||||
|
}
|
||||||
|
]"
|
||||||
|
@mouseenter="showClose = true"
|
||||||
|
@mouseleave="showClose = false">
|
||||||
|
<div class="el-input__icon el-range__icon" :class="prefixIcon">
|
||||||
|
<slot name="prepend"></slot>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
autocomplete="off"
|
||||||
|
:placeholder="startPlaceholder"
|
||||||
|
:value="userInput && userInput[0]"
|
||||||
|
:disabled="inputDisabled"
|
||||||
|
:readonly="readonly"
|
||||||
|
:name="name && name[0]"
|
||||||
|
@input="handleStartInput"
|
||||||
|
@change="handleStartChange"
|
||||||
|
@focus="focused = true"
|
||||||
|
@blur="focused = false"
|
||||||
|
class="el-range-input">
|
||||||
|
<slot name="range-separator">
|
||||||
|
<span class="el-range-separator">{{ rangeSeparator }}</span>
|
||||||
|
</slot>
|
||||||
|
<input
|
||||||
|
autocomplete="off"
|
||||||
|
:placeholder="endPlaceholder"
|
||||||
|
:value="userInput && userInput[1]"
|
||||||
|
:disabled="inputDisabled"
|
||||||
|
:readonly="readonly"
|
||||||
|
:name="name && name[1]"
|
||||||
|
@input="handleEndInput"
|
||||||
|
@change="handleEndChange"
|
||||||
|
@focus="focused = true"
|
||||||
|
@blur="focused = false"
|
||||||
|
class="el-range-input">
|
||||||
|
<i class="el-input__icon el-range__close-icon"
|
||||||
|
:class="[showClear ? 'el-icon-circle-close' : '']"
|
||||||
|
@click="handleClickClear">
|
||||||
|
</i>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import emitter from 'element-ui/src/mixins/emitter';
|
||||||
|
|
||||||
|
function isNumber (val) {
|
||||||
|
var regPos = /^\d+(\.\d+)?$/; // 非负浮点数
|
||||||
|
var regNeg = /^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$/; // 负浮点数
|
||||||
|
if (regPos.test(val) || regNeg.test(val)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
name: 'InputNumberRange',
|
||||||
|
componentName: 'InputNumberRange',
|
||||||
|
mixins: [emitter],
|
||||||
|
props: {
|
||||||
|
/**
|
||||||
|
* 绑定字段
|
||||||
|
*/
|
||||||
|
value: {
|
||||||
|
type: Array,
|
||||||
|
default: function () {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 组件大小(medium / small / mini)
|
||||||
|
*/
|
||||||
|
size: String,
|
||||||
|
/**
|
||||||
|
* 禁用
|
||||||
|
*/
|
||||||
|
disabled: Boolean,
|
||||||
|
/**
|
||||||
|
* 完全只读
|
||||||
|
*/
|
||||||
|
readonly: Boolean,
|
||||||
|
/**
|
||||||
|
* 是否显示清除按钮
|
||||||
|
*/
|
||||||
|
clearable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 自定义头部图标的类名
|
||||||
|
*/
|
||||||
|
prefixIcon: String,
|
||||||
|
/**
|
||||||
|
* 范围选择时最小值的占位内容
|
||||||
|
*/
|
||||||
|
startPlaceholder: String,
|
||||||
|
/**
|
||||||
|
* 范围选择时最大值的占位内容
|
||||||
|
*/
|
||||||
|
endPlaceholder: String,
|
||||||
|
/**
|
||||||
|
* 原生属性
|
||||||
|
*/
|
||||||
|
name: {
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 选择范围时的分隔符
|
||||||
|
*/
|
||||||
|
rangeSeparator: {
|
||||||
|
type: String,
|
||||||
|
default: '-'
|
||||||
|
},
|
||||||
|
validateEvent: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
hovering: false,
|
||||||
|
focused: false,
|
||||||
|
userInput: this.value,
|
||||||
|
showClose: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
inject: {
|
||||||
|
elForm: {
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
elFormItem: {
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
_elFormItemSize () {
|
||||||
|
return (this.elFormItem || {}).elFormItemSize;
|
||||||
|
},
|
||||||
|
inputSize () {
|
||||||
|
let temp = this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
|
||||||
|
return temp;
|
||||||
|
},
|
||||||
|
inputDisabled () {
|
||||||
|
return this.disabled || (this.elForm || {}).disabled;
|
||||||
|
},
|
||||||
|
showClear () {
|
||||||
|
let temp = this.clearable && !this.inputDisabled && !this.readonly && this.showClose &&
|
||||||
|
this.userInput != null && Array.isArray(this.userInput) && this.userInput.length > 0 &&
|
||||||
|
(this.userInput[0] != null || this.userInput[1] != null);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleStartInput (event) {
|
||||||
|
if (this.userInput) {
|
||||||
|
this.userInput = [event.target.value, this.userInput[1]];
|
||||||
|
} else {
|
||||||
|
this.userInput = [event.target.value, null];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleEndInput (event) {
|
||||||
|
if (this.userInput) {
|
||||||
|
this.userInput = [this.userInput[0], event.target.value];
|
||||||
|
} else {
|
||||||
|
this.userInput = [null, event.target.value];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleStartChange (event) {
|
||||||
|
let value = this.userInput && this.userInput[0];
|
||||||
|
value = isNumber(value) ? value : null;
|
||||||
|
value = value ? Number.parseFloat(value) : null;
|
||||||
|
if (this.userInput) {
|
||||||
|
this.userInput[0] = value;
|
||||||
|
} else {
|
||||||
|
this.userInput = [value, null];
|
||||||
|
}
|
||||||
|
event.srcElement.value = value;
|
||||||
|
this.emitInput(this.userInput);
|
||||||
|
},
|
||||||
|
handleEndChange (event) {
|
||||||
|
let value = this.userInput && this.userInput[1];
|
||||||
|
value = isNumber(value) ? value : null;
|
||||||
|
value = value ? Number.parseFloat(value) : null;
|
||||||
|
if (this.userInput) {
|
||||||
|
this.userInput[1] = value;
|
||||||
|
} else {
|
||||||
|
this.userInput = [null, value];
|
||||||
|
}
|
||||||
|
event.srcElement.value = value;
|
||||||
|
this.emitInput(this.userInput);
|
||||||
|
},
|
||||||
|
handleClickClear () {
|
||||||
|
this.userInput = undefined;
|
||||||
|
this.emitInput(this.userInput);
|
||||||
|
},
|
||||||
|
valueEquals (val, oldVal) {
|
||||||
|
return JSON.stringify(val) === JSON.stringify(oldVal);
|
||||||
|
},
|
||||||
|
emitInput (values) {
|
||||||
|
this.$emit('input', values);
|
||||||
|
this.$emit('change', values);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value: {
|
||||||
|
handler: function (val, oldVal) {
|
||||||
|
if (!this.valueEquals(val, oldVal) && this.validateEvent) {
|
||||||
|
this.dispatch('ElFormItem', 'el.form.change', val);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deep: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
<template>
|
||||||
|
<el-progress v-bind="$attrs" :percentage="getPercentage" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Progress',
|
||||||
|
props: {
|
||||||
|
/**
|
||||||
|
* 组件最小值
|
||||||
|
*/
|
||||||
|
min: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 组件最大值
|
||||||
|
*/
|
||||||
|
max: {
|
||||||
|
type: Number,
|
||||||
|
default: 100
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 组件当前值
|
||||||
|
*/
|
||||||
|
value: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
getPercentage () {
|
||||||
|
let value = Math.min(this.max, Math.max(this.min, this.value));
|
||||||
|
value = value - this.min;
|
||||||
|
if ((this.max - this.min) === 0) {
|
||||||
|
value = 0;
|
||||||
|
} else {
|
||||||
|
value = ((value * 100) / (this.max - this.min));
|
||||||
|
}
|
||||||
|
return Number.isInteger(value) ? value : parseInt(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
<template>
|
||||||
|
<div class="uditor-class" ref="editor"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import WEditor from 'wangeditor';
|
||||||
|
|
||||||
|
const defaultConfigs = {
|
||||||
|
uploadImgServer: undefined,
|
||||||
|
uploadFileName: 'imageFile',
|
||||||
|
uploadImgMaxSize: 1 * 1024 * 1024,
|
||||||
|
uploadImgShowBase64: true,
|
||||||
|
uploadImgMaxLength: 5,
|
||||||
|
uploadImgParams: undefined,
|
||||||
|
uploadImgParamsWithUrl: true,
|
||||||
|
withCredentials: true,
|
||||||
|
uploadImgTimeout: 5000,
|
||||||
|
uploadImgHeaders: undefined,
|
||||||
|
uploadImgHooks: undefined,
|
||||||
|
zIndex: 0,
|
||||||
|
lang: undefined,
|
||||||
|
pasteFilterStyle: true,
|
||||||
|
pasteIgnoreImg: false,
|
||||||
|
onchangeTimeout: 10,
|
||||||
|
menus: [
|
||||||
|
// 标题
|
||||||
|
'head',
|
||||||
|
// 粗体
|
||||||
|
'bold',
|
||||||
|
// 字号
|
||||||
|
'fontSize',
|
||||||
|
// 字体
|
||||||
|
'fontName',
|
||||||
|
// 斜体
|
||||||
|
'italic',
|
||||||
|
// 下划线
|
||||||
|
'underline',
|
||||||
|
// 删除线
|
||||||
|
'strikeThrough',
|
||||||
|
// 文字颜色
|
||||||
|
'foreColor',
|
||||||
|
// 背景颜色
|
||||||
|
'backColor',
|
||||||
|
// 插入链接
|
||||||
|
'link',
|
||||||
|
// 列表
|
||||||
|
'list',
|
||||||
|
// 对齐方式
|
||||||
|
'justify',
|
||||||
|
// 引用
|
||||||
|
'quote',
|
||||||
|
// 插入图片
|
||||||
|
'image',
|
||||||
|
// 撤销
|
||||||
|
'undo',
|
||||||
|
// 重复
|
||||||
|
'redo'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
/**
|
||||||
|
* 绑定字段
|
||||||
|
*/
|
||||||
|
value: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 配置项,详情请参考wangEditor文档
|
||||||
|
*/
|
||||||
|
config: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return defaultConfigs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
editor: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
getConfigs () {
|
||||||
|
return {...this.config, ...defaultConfigs};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.editor = new WEditor(this.$refs.editor);
|
||||||
|
this.editor.customConfig = {...this.getConfigs};
|
||||||
|
this.editor.customConfig.pasteTextHandle = (content) => {
|
||||||
|
// content 即粘贴过来的内容(html 或 纯文本),可进行自定义处理然后返回
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
this.editor.customConfig.linkImgCallback = (url) => {
|
||||||
|
console.log(url) // url 即插入图片的地址
|
||||||
|
}
|
||||||
|
this.editor.customConfig.linkCheck = (text, link) => {
|
||||||
|
return true // 返回 true 表示校验成功
|
||||||
|
// return '验证失败' // 返回字符串,即校验失败的提示信息
|
||||||
|
}
|
||||||
|
|
||||||
|
this.editor.customConfig.linkImgCheck = (src) => {
|
||||||
|
return true // 返回 true 表示校验成功
|
||||||
|
// return '验证失败' // 返回字符串,即校验失败的提示信息
|
||||||
|
}
|
||||||
|
// 失去焦点后更新数据
|
||||||
|
this.editor.customConfig.onblur = (html) => {
|
||||||
|
console.log(html)
|
||||||
|
this.$emit('input', html);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.editor.create();
|
||||||
|
this.editor.txt.html(this.value);
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value: {
|
||||||
|
handler (newValue) {
|
||||||
|
if (this.editor) this.editor.txt.html(this.value);
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
<template>
|
||||||
|
<el-table-column v-bind="$attrs">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<orange-progress :stroke-width="strokeWidth" :type="type" :text-inside="textInside" :status="status" :color="color"
|
||||||
|
:width="width" :show-text="showText" :min="getMinValue(scope.row)" :max="getMaxValue(scope.row)"
|
||||||
|
:value="getValue(scope.row)" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Progress from '@/components/Progress/index.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'TableProgressColumn',
|
||||||
|
components: {
|
||||||
|
'orange-progress': Progress
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
/**
|
||||||
|
* 固定值最小值
|
||||||
|
*/
|
||||||
|
min: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 固定值最大值
|
||||||
|
*/
|
||||||
|
max: {
|
||||||
|
type: Number,
|
||||||
|
default: 100
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 固定值当前值
|
||||||
|
*/
|
||||||
|
value: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 表格最小值字段名
|
||||||
|
*/
|
||||||
|
minColumn: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 表格最大值字段名
|
||||||
|
*/
|
||||||
|
maxColumn: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 表格当前值字段名
|
||||||
|
*/
|
||||||
|
valueColumn: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 进度条的宽度,单位 px
|
||||||
|
*/
|
||||||
|
strokeWidth: {
|
||||||
|
type: Number,
|
||||||
|
default: 16
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 进度条类型(line/circle/dashboard)
|
||||||
|
*/
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: 'line'
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 进度条显示文字内置在进度条内(只在 type=line 时可用)
|
||||||
|
*/
|
||||||
|
textInside: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 进度条当前状态(success/exception/warning)
|
||||||
|
*/
|
||||||
|
status: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 进度条背景色(会覆盖 status 状态颜色)
|
||||||
|
*/
|
||||||
|
color: {
|
||||||
|
type: [String, Function, Array]
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 环形进度条画布宽度(只在 type 为 circle 或 dashboard 时可用)
|
||||||
|
*/
|
||||||
|
width: {
|
||||||
|
type: Number,
|
||||||
|
default: 126
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 是否显示进度条文字内容
|
||||||
|
*/
|
||||||
|
showText: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getValue (row) {
|
||||||
|
return this.valueColumn ? row[this.valueColumn] : this.value;
|
||||||
|
},
|
||||||
|
getMinValue (row) {
|
||||||
|
return this.minColumn ? row[this.minColumn] : this.min;
|
||||||
|
},
|
||||||
|
getMaxValue (row) {
|
||||||
|
return this.maxColumn ? row[this.maxColumn] : this.max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,300 @@
|
|||||||
|
<template>
|
||||||
|
<el-popover ref="popover" placement="bottom-start" trigger="click" popper-class="tree-select-popover"
|
||||||
|
:width="width" @show="onShowPopover">
|
||||||
|
<el-scrollbar :style="{'height': this.height, 'min-width': this.width}" ref="scrollbar">
|
||||||
|
<el-tree ref="dropdownTree" :props="getTreeProps" :highlightCurrent="highlightCurrent" :nodeKey="getDataProps.value"
|
||||||
|
:defaultExpandAll="defaultExpandAll" :expandOnClickNode="expandOnClickNode" :checkOnClickNode="checkOnClickNode"
|
||||||
|
:autoExpandParent="autoExpandParent" :defaultExpandedKeys="defaultExpandedKeys" :showCheckbox="showCheckbox"
|
||||||
|
:checkStrictly="checkStrictly" :defaultCheckedKeys="defaultCheckedKeys" :currentNodeKey="getCurrentNodeKey"
|
||||||
|
:accordion="accordion" :indent="indent" :iconClass="iconClass" :load="loadChildrenNodes" lazy :show-checkbox="multiple"
|
||||||
|
@node-click="onTreeNodeClick" @check="onTreeNodeCheck">
|
||||||
|
<span :style="getNodeStyle(data)" slot-scope="{ node, data }">{{data[getDataProps.label]}}</span>
|
||||||
|
</el-tree>
|
||||||
|
</el-scrollbar>
|
||||||
|
<el-select slot="reference" v-model="selectKeys" :multiple="multiple" :disabled="false" :size="size"
|
||||||
|
:clearable="clearable" :collapseTags="collapseTags" :placeholder="placeholder" popper-class="select-tree-popper"
|
||||||
|
@clear="onClear" @remove-tag="onClear">
|
||||||
|
<el-option v-for="item in selectNodes" :key="item[getDataProps.value]"
|
||||||
|
:value="item[getDataProps.value]" :label="item[getDataProps.label]" />
|
||||||
|
</el-select>
|
||||||
|
</el-popover>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { findTreeNode } from '@/utils';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'TreeSelect',
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: [String, Number]
|
||||||
|
},
|
||||||
|
multiple: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: String,
|
||||||
|
default: '200px'
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
type: String,
|
||||||
|
default: '300px'
|
||||||
|
},
|
||||||
|
activeColor: {
|
||||||
|
type: String,
|
||||||
|
default: '#EF5E1C'
|
||||||
|
},
|
||||||
|
clearable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
collapseTags: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
placeholder: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
loading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
loadingText: {
|
||||||
|
type: String,
|
||||||
|
default: '加载中'
|
||||||
|
},
|
||||||
|
// 树属性
|
||||||
|
data: {
|
||||||
|
type: Array
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {
|
||||||
|
label: 'label',
|
||||||
|
value: 'value',
|
||||||
|
parentKey: 'parentId',
|
||||||
|
children: 'children',
|
||||||
|
disabled: 'disabled'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
defaultExpandAll: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
expandOnClickNode: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
checkOnClickNode: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
autoExpandParent: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
defaultExpandedKeys: {
|
||||||
|
type: Array
|
||||||
|
},
|
||||||
|
checkStrictly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
currentNodeKey: {
|
||||||
|
type: [String, Number]
|
||||||
|
},
|
||||||
|
accordion: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
indent: {
|
||||||
|
type: Number,
|
||||||
|
default: 16
|
||||||
|
},
|
||||||
|
iconClass: {
|
||||||
|
type: String
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
rootNode: undefined,
|
||||||
|
rootResolve: undefined,
|
||||||
|
allTreeNode: [],
|
||||||
|
selectNodes: [],
|
||||||
|
scrollTop: 0,
|
||||||
|
selectKeys: undefined
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onShowPopover () {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$refs.scrollbar.wrap.scrollTop = this.scrollTop;
|
||||||
|
// this.$refs.scrollbar.update();
|
||||||
|
}, 20);
|
||||||
|
if (!this.multiple) {
|
||||||
|
this.$refs.dropdownTree.setCurrentKey(this.value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onClear () {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$emit('input', this.selectKeys);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onTreeNodeClick (data, node) {
|
||||||
|
this.$refs.popover.showPopper = false;
|
||||||
|
if (!this.multiple) {
|
||||||
|
this.scrollTop = this.$refs.scrollbar.wrap.scrollTop;
|
||||||
|
this.$emit('input', data[this.getDataProps.value]);
|
||||||
|
this.$emit('change', data[this.getDataProps.value]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onTreeNodeCheck (data, {checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys}) {
|
||||||
|
this.scrollTop = this.$refs.scrollbar.wrap.scrollTop
|
||||||
|
this.$emit('input', checkedKeys);
|
||||||
|
this.$emit('change', checkedKeys);
|
||||||
|
},
|
||||||
|
parseNode (node) {
|
||||||
|
if (Array.isArray(node) && node.length > 0) {
|
||||||
|
node.forEach((item) => {
|
||||||
|
item['__node_is_leaf__'] = !(Array.isArray(item[this.getDataProps.children]) && item[this.getDataProps.children].length > 0);
|
||||||
|
});
|
||||||
|
return node;
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
loadChildrenNodes (node, resolve) {
|
||||||
|
if (node.level === 0) {
|
||||||
|
this.rootNode = node;
|
||||||
|
this.rootResolve = resolve;
|
||||||
|
return resolve(this.parseNode(this.allTreeNode));
|
||||||
|
} else {
|
||||||
|
return resolve(this.parseNode(node.data[this.getDataProps.children]));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getNodeStyle (data) {
|
||||||
|
if (!this.multiple && (this.selectNodes[0] || {})[this.getDataProps.value] === data[this.getDataProps.value]) {
|
||||||
|
return {
|
||||||
|
color: this.activeColor,
|
||||||
|
'font-weight': 700
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
showCheckbox () {
|
||||||
|
return this.multiple;
|
||||||
|
},
|
||||||
|
getCurrentNodeKey () {
|
||||||
|
if (!this.multiple && Array.isArray(this.selectNodes) && this.selectNodes.length > 0) {
|
||||||
|
return this.selectNodes[0][this.getDataProps.value];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
highlightCurrent () {
|
||||||
|
return this.multiple;
|
||||||
|
},
|
||||||
|
defaultCheckedKeys () {
|
||||||
|
return this.multiple ? this.selectNodes : undefined
|
||||||
|
},
|
||||||
|
getDataProps () {
|
||||||
|
return {
|
||||||
|
label: this.props.label || 'label',
|
||||||
|
value: this.props.value || 'value',
|
||||||
|
parentKey: this.props.parentKey || 'parentId',
|
||||||
|
children: this.props.children || 'children',
|
||||||
|
disabled: this.props.disabled || 'disabled'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getTreeProps () {
|
||||||
|
return {
|
||||||
|
label: this.getDataProps.label,
|
||||||
|
children: '__children_list__',
|
||||||
|
disabled: this.getDataProps.disabled,
|
||||||
|
isLeaf: '__node_is_leaf__'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
data: {
|
||||||
|
handler (newValue, oldValue) {
|
||||||
|
this.allTreeNode = newValue;
|
||||||
|
if (this.rootNode != null && this.rootResolve != null) {
|
||||||
|
this.rootNode.childNodes = [];
|
||||||
|
this.loadChildrenNodes(this.rootNode, this.rootResolve);
|
||||||
|
}
|
||||||
|
this.selectNodes = [];
|
||||||
|
if (this.multiple) {
|
||||||
|
if (Array.isArray(this.value)) {
|
||||||
|
this.value.forEach((item) => {
|
||||||
|
let data = findTreeNode(this.allTreeNode, item, this.getDataProps.value, this.getDataProps.children);
|
||||||
|
if (data) this.selectNodes.push(data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let data = findTreeNode(this.allTreeNode, this.value, this.getDataProps.value, this.getDataProps.children);
|
||||||
|
if (data) this.selectNodes.push(data);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
handler (newValue) {
|
||||||
|
this.selectNodes = [];
|
||||||
|
if (Array.isArray(newValue)) {
|
||||||
|
newValue.forEach((item) => {
|
||||||
|
let data = findTreeNode(this.allTreeNode, item, this.getDataProps.value, this.getDataProps.children);
|
||||||
|
if (data) this.selectNodes.push(data);
|
||||||
|
});
|
||||||
|
this.selectKeys = newValue;
|
||||||
|
} else {
|
||||||
|
let data = findTreeNode(this.allTreeNode, newValue, this.getDataProps.value, this.getDataProps.children);
|
||||||
|
if (data) this.selectNodes.push(data);
|
||||||
|
this.selectKeys = newValue;
|
||||||
|
}
|
||||||
|
if (this.$refs.dropdownTree) {
|
||||||
|
this.multiple ? this.$refs.dropdownTree.setCheckedKeys(newValue) : this.$refs.dropdownTree.setCurrentKey(newValue);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.select-tree-popper {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.tree-select-popover {
|
||||||
|
padding: 6px 0px;
|
||||||
|
}
|
||||||
|
.tree-select-popover .popper__arrow {
|
||||||
|
left: 35px!important;
|
||||||
|
}
|
||||||
|
.tree-select-popover .el-tree .el-tree-node__content {
|
||||||
|
height: 34px;
|
||||||
|
line-height: 34px;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
.tree-select-popover .el-tree .el-tree-node.is-current .el-tree-node__content {
|
||||||
|
color: #fdb95c;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
.current-node {
|
||||||
|
color: #EF5E1C;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
module.exports = {
|
||||||
|
baseUrl: 'http://localhost:9998/',
|
||||||
|
projectName: 'UAA应用管理项目'
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
const projectConfig = require('../config/' + process.env.NODE_ENV);
|
||||||
|
|
||||||
|
export const globalConfig = {
|
||||||
|
httpOption: {
|
||||||
|
showMask: true,
|
||||||
|
showError: true
|
||||||
|
},
|
||||||
|
axiosOption: {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default projectConfig;
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
module.exports = {
|
||||||
|
baseUrl: 'http://localhost:9998/',
|
||||||
|
projectName: 'UAA应用管理项目'
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
import { SortableData } from './sortableData';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拖拽排序指令
|
||||||
|
*/
|
||||||
|
Vue.directive('sortable', {
|
||||||
|
inserted: function (el, binding, vnode) {
|
||||||
|
let sortableData = binding.value;
|
||||||
|
if (sortableData == null || !(sortableData instanceof SortableData)) return;
|
||||||
|
|
||||||
|
sortableData.init(vnode.elm);
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
import sortable from 'sortablejs'
|
||||||
|
/**
|
||||||
|
* 拖拽排序对象
|
||||||
|
* expample
|
||||||
|
* <ul v-sortable="new SortableData(data)">
|
||||||
|
* <li>A</li>
|
||||||
|
* <li>B</li>
|
||||||
|
* <li>C</li>
|
||||||
|
* <li>D</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
export class SortableData {
|
||||||
|
constructor (data, group) {
|
||||||
|
this.list = data;
|
||||||
|
this.group = group;
|
||||||
|
this.ghostClass = 'sortable-ghost';
|
||||||
|
this.sortable = null;
|
||||||
|
this.disabled = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
setData (list) {
|
||||||
|
this.list = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
getElement (el) {
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
|
||||||
|
onEnd (oldIndex, newIndex) {
|
||||||
|
if (oldIndex === newIndex || this.list == null) return;
|
||||||
|
let targetRow = this.list.splice(oldIndex, 1)[0]
|
||||||
|
this.list.splice(newIndex, 0, targetRow);
|
||||||
|
};
|
||||||
|
|
||||||
|
init (el) {
|
||||||
|
var _this = this;
|
||||||
|
|
||||||
|
var _option = {};
|
||||||
|
if (this.ghostClass != null) _option.ghostClass = this.ghostClass;
|
||||||
|
if (this.group != null) _option.group = this.group;
|
||||||
|
if (this.disabled != null) _option.disabled = this.disabled;
|
||||||
|
// 列表中能拖动的dom的选择器(例如:.drag-item)
|
||||||
|
if (this.draggable != null) _option.draggable = this.draggable;
|
||||||
|
// 列表中拖动项,拖动把柄的选择器,只有点击这个选择出来的dom才可以开始拖动(例如:.drag-handle)
|
||||||
|
if (this.handle != null) _option.handle = this.handle;
|
||||||
|
_option.setData = function (dataTransfer) {
|
||||||
|
dataTransfer.setData('Text', '');
|
||||||
|
};
|
||||||
|
_option.onEnd = function (evt) {
|
||||||
|
_this.onEnd(evt.oldIndex, evt.newIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.sortable = sortable.create(_this.getElement(el), _option);
|
||||||
|
};
|
||||||
|
|
||||||
|
release () {
|
||||||
|
if (this.sortable != null) this.sortable.destroy();
|
||||||
|
this.sortable = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,185 @@
|
|||||||
|
import Vue from 'vue';
|
||||||
|
import { Loading, Message } from 'element-ui';
|
||||||
|
import request from './request';
|
||||||
|
import requestUrl from './requestUrl';
|
||||||
|
import merge from 'lodash/merge';
|
||||||
|
import { globalConfig } from '@/core/config';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 遮罩管理,多次调用支持引用计数
|
||||||
|
*/
|
||||||
|
class LoadingManager {
|
||||||
|
constructor (options) {
|
||||||
|
this.options = options;
|
||||||
|
this.refCount = 0;
|
||||||
|
this.loading = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
showMask () {
|
||||||
|
this.loading = Loading.service(this.options);
|
||||||
|
this.refCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
hideMask () {
|
||||||
|
if (this.refCount <= 1 && this.loading != null) {
|
||||||
|
this.loading.close();
|
||||||
|
this.loading = null;
|
||||||
|
}
|
||||||
|
this.refCount--;
|
||||||
|
this.refCount = Math.max(0, this.refCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadingManager = new LoadingManager({
|
||||||
|
fullscreen: true,
|
||||||
|
background: 'rgba(0, 0, 0, 0.1)'
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* post请求
|
||||||
|
* @param {String} url 请求的url
|
||||||
|
* @param {Object} params 请求参数
|
||||||
|
* @param {Object} options axios设置项
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
const fetchPost = function (url, params, options) {
|
||||||
|
if (options == null) return {};
|
||||||
|
let tempOptions = {
|
||||||
|
...options,
|
||||||
|
method: 'post',
|
||||||
|
url: requestUrl(url),
|
||||||
|
data: params
|
||||||
|
};
|
||||||
|
|
||||||
|
return request(tempOptions);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* get请求
|
||||||
|
* @param {String} url 请求的url
|
||||||
|
* @param {Object} params 请求参数
|
||||||
|
* @param {Object} options axios设置项
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
const fetchGet = function (url, params, options) {
|
||||||
|
if (options == null) return {};
|
||||||
|
let tempOptions = {
|
||||||
|
...options,
|
||||||
|
method: 'get',
|
||||||
|
url: requestUrl(url),
|
||||||
|
params
|
||||||
|
};
|
||||||
|
return request(tempOptions);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 下载请求
|
||||||
|
* @param {String} url 请求的url
|
||||||
|
* @param {Object} params 请求参数
|
||||||
|
* @param {String} fileName 下载后保存的文件名
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
const fetchDownload = function (url, params, fileName) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
request({
|
||||||
|
url: requestUrl(url),
|
||||||
|
method: 'post',
|
||||||
|
data: params,
|
||||||
|
responseType: 'blob',
|
||||||
|
transformResponse: function (data) {
|
||||||
|
return (data instanceof Blob && data.size > 0) ? data : undefined;
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
if (res.data == null) {
|
||||||
|
reject(new Error('下载文件失败'));
|
||||||
|
} else {
|
||||||
|
let blobData = new Blob([res.data], { type: 'application/octet-stream' });
|
||||||
|
let blobUrl = window.URL.createObjectURL(blobData);
|
||||||
|
let linkDom = document.createElement('a');
|
||||||
|
linkDom.style.display = 'none';
|
||||||
|
linkDom.href = blobUrl;
|
||||||
|
linkDom.setAttribute('download', fileName);
|
||||||
|
if (typeof linkDom.download === 'undefined') {
|
||||||
|
linkDom.setAttribute('target', '_blank');
|
||||||
|
}
|
||||||
|
document.body.appendChild(linkDom);
|
||||||
|
linkDom.click();
|
||||||
|
document.body.removeChild(linkDom);
|
||||||
|
window.URL.revokeObjectURL(blobData);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
}).catch(e => {
|
||||||
|
if (e instanceof Blob) {
|
||||||
|
let reader = new FileReader();
|
||||||
|
reader.onload = function () {
|
||||||
|
let jsonObj = JSON.parse(reader.result);
|
||||||
|
reject((jsonObj || {}).errorMessage || '下载文件失败');
|
||||||
|
}
|
||||||
|
reader.readAsText(e);
|
||||||
|
} else {
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 数据请求
|
||||||
|
* @param {String} url 请求的url
|
||||||
|
* @param {String} type 请求类型(get,post)
|
||||||
|
* @param {Object} params 请求参数
|
||||||
|
* @param {Object} axiosOption axios设置
|
||||||
|
* @param {Object} options 显示设置
|
||||||
|
*/
|
||||||
|
const doUrl = function (url, type, params, axiosOption, options) {
|
||||||
|
options = merge(globalConfig.httpOption, options);
|
||||||
|
axiosOption = merge(globalConfig.axiosOption, axiosOption);
|
||||||
|
if (type == null || type === '') type = 'post';
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (options.showMask) loadingManager.showMask();
|
||||||
|
let ajaxCall = null;
|
||||||
|
if (type.toLowerCase() === 'get') {
|
||||||
|
ajaxCall = fetchGet(url, params, axiosOption);
|
||||||
|
} else if (type.toLowerCase() === 'post') {
|
||||||
|
ajaxCall = fetchPost(url, params, axiosOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ajaxCall != null) {
|
||||||
|
ajaxCall.then(res => {
|
||||||
|
if (options.showMask) loadingManager.hideMask();
|
||||||
|
if (res.data && res.data.success) {
|
||||||
|
resolve(res.data);
|
||||||
|
} else {
|
||||||
|
if (options.showError) {
|
||||||
|
Message.error({
|
||||||
|
showClose: true,
|
||||||
|
message: res.data.errorMessage ? res.data.errorMessage : '数据请求失败'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
reject(res.data);
|
||||||
|
}
|
||||||
|
}).catch(e => {
|
||||||
|
if (options.showMask) loadingManager.hideMask();
|
||||||
|
if (options.showError) {
|
||||||
|
Message.error({
|
||||||
|
showClose: true,
|
||||||
|
message: e.errorMessage ? e.errorMessage : '网络请求错误'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
reject(e);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (options.showMask) loadingManager.hideMask();
|
||||||
|
reject(new Error('错误的请求类型 - ' + type));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Vue.prototype.download = fetchDownload;
|
||||||
|
Vue.prototype.doUrl = doUrl;
|
||||||
|
Vue.prototype.loadingManager = loadingManager;
|
||||||
|
|
||||||
|
export default {
|
||||||
|
doUrl,
|
||||||
|
fetchPost,
|
||||||
|
fetchGet,
|
||||||
|
fetchDownload
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
import router from '@/router';
|
||||||
|
import dialog from '@/components/Dialog';
|
||||||
|
import JSONbig from 'json-bigint';
|
||||||
|
|
||||||
|
// 创建axios实例
|
||||||
|
const service = axios.create({
|
||||||
|
timeout: 1000 * 30,
|
||||||
|
withCredentials: true,
|
||||||
|
headers: {
|
||||||
|
// 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
|
||||||
|
'Content-Type': 'application/json; charset=utf-8'
|
||||||
|
},
|
||||||
|
transformResponse: [
|
||||||
|
function (data) {
|
||||||
|
if (typeof data === 'string') {
|
||||||
|
const JSONbigString = new JSONbig({storeAsString: true});
|
||||||
|
return JSONbigString.parse(data);
|
||||||
|
} else {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
// request拦截器
|
||||||
|
service.interceptors.request.use(
|
||||||
|
config => {
|
||||||
|
let token = window.sessionStorage.getItem('token');
|
||||||
|
let menuIdJsonStr = window.sessionStorage.getItem('currentMenuId');
|
||||||
|
let currentMenuId;
|
||||||
|
if (menuIdJsonStr != null) {
|
||||||
|
currentMenuId = (JSON.parse(menuIdJsonStr) || {}).data;
|
||||||
|
}
|
||||||
|
if (token != null) config.headers['Authorization'] = token;
|
||||||
|
if (currentMenuId != null) config.headers['MenuId'] = currentMenuId;
|
||||||
|
return config
|
||||||
|
}, error => {
|
||||||
|
return Promise.reject(error)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// response拦截器
|
||||||
|
service.interceptors.response.use(
|
||||||
|
response => {
|
||||||
|
if (response.data && response.data.errorCode === 'UNAUTHORIZED_LOGIN') { // 401, token失效
|
||||||
|
dialog.closeAll();
|
||||||
|
router.push({ name: 'login' })
|
||||||
|
} else {
|
||||||
|
if (response.headers['refreshedtoken'] != null) {
|
||||||
|
window.sessionStorage.setItem('token', response.headers['refreshedtoken']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return response
|
||||||
|
}, error => {
|
||||||
|
let response = error.response;
|
||||||
|
|
||||||
|
if (response && response.data) {
|
||||||
|
if (response.data.errorCode === 'UNAUTHORIZED_LOGIN') {
|
||||||
|
dialog.closeAll();
|
||||||
|
router.push({ name: 'login' });
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.reject(response.data);
|
||||||
|
} else {
|
||||||
|
return Promise.reject(new Error({
|
||||||
|
errorMessage: '数据获取失败,请稍后再试'
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export default service
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import projectConfig from '@/core/config';
|
||||||
|
import { objectToQueryString } from '@/utils';
|
||||||
|
console.log(process.env.NODE_ENV, projectConfig);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求地址统一处理/组装
|
||||||
|
* @param actionName action方法名称
|
||||||
|
*/
|
||||||
|
export default function (actionName) {
|
||||||
|
if (actionName != null && actionName !== '') {
|
||||||
|
if (actionName.substr(0, 1) === '/') actionName = actionName.substr(1);
|
||||||
|
}
|
||||||
|
return projectConfig.baseUrl + actionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildGetUrl (actionName, params) {
|
||||||
|
let queryString = objectToQueryString(params);
|
||||||
|
if (actionName != null && actionName !== '') {
|
||||||
|
if (actionName.substr(0, 1) === '/') actionName = actionName.substr(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return projectConfig.baseUrl + actionName + (queryString == null ? '' : ('?' + queryString));
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
projectConfig
|
||||||
|
}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
import Vue from 'vue';
|
||||||
|
import Request from '@/core/http/request.js';
|
||||||
|
import { mapMutations, mapGetters } from 'vuex';
|
||||||
|
|
||||||
|
// 全局mixin对象
|
||||||
|
const globalMixin = {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
isHttpLoading: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 是否显示遮罩
|
||||||
|
* @param {Boolean} isShow 是否显示
|
||||||
|
*/
|
||||||
|
showMask (isShow) {
|
||||||
|
isShow ? this.loadingManager.showMask() : this.loadingManager.hideMask();
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 判读用户是否有权限
|
||||||
|
* @param {String} permCode 权限字
|
||||||
|
*/
|
||||||
|
checkPermCodeExist (permCode) {
|
||||||
|
if (this.getUserInfo.permCodeSet != null) {
|
||||||
|
return this.getUserInfo.permCodeSet.has(permCode);
|
||||||
|
} else {
|
||||||
|
return this.getUserInfo.isAdmin;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 将输入的值转换成指定的类型
|
||||||
|
* @param {Any} value
|
||||||
|
* @param {String} type 要转换的类型(integer、float、boolean、string)
|
||||||
|
*/
|
||||||
|
parseParams (value, type = 'string') {
|
||||||
|
if (value == null) return value;
|
||||||
|
switch (type) {
|
||||||
|
case 'integer': return Number.parseInt(value);
|
||||||
|
case 'float': return Number.parseFloat(value);
|
||||||
|
case 'boolean': return (value === 'true' || value);
|
||||||
|
default: return String(value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 将输入值转换为执行的类型数组
|
||||||
|
* @param {Array} value 输入数组
|
||||||
|
* @param {String} type 要转换的类型(integer、float、boolean、string)
|
||||||
|
*/
|
||||||
|
parseArrayParams (value, type = 'string') {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value.map((item) => {
|
||||||
|
switch (type) {
|
||||||
|
case 'integer': return Number.parseInt(item);
|
||||||
|
case 'float': return Number.parseFloat(item);
|
||||||
|
case 'boolean': return (item === 'true' || item);
|
||||||
|
default: return String(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 下载上传的文件
|
||||||
|
* @param {*} url 下载文件的url
|
||||||
|
* @param {*} fileName 下载文件名
|
||||||
|
*/
|
||||||
|
downloadFile (url, fileName) {
|
||||||
|
console.log(fileName);
|
||||||
|
Request({
|
||||||
|
url: url,
|
||||||
|
method: 'get',
|
||||||
|
responseType: 'blob',
|
||||||
|
transformResponse: function (data) {
|
||||||
|
console.log(data);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
console.log(res);
|
||||||
|
let data = res.data;
|
||||||
|
if (res.status === 200 && data instanceof Blob) {
|
||||||
|
let url = window.URL.createObjectURL(data);
|
||||||
|
let link = document.createElement('a');
|
||||||
|
link.style.display = 'none';
|
||||||
|
link.href = url;
|
||||||
|
link.setAttribute('download', fileName);
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
document.body.removeChild(link);
|
||||||
|
} else {
|
||||||
|
this.$message.error('下载文件失败');
|
||||||
|
}
|
||||||
|
}).catch(e => {
|
||||||
|
let reader = new FileReader();
|
||||||
|
reader.onload = () => {
|
||||||
|
let jsonObj = JSON.parse(reader.result);
|
||||||
|
this.$message.error((jsonObj || {}).errorMessage || '下载文件失败');
|
||||||
|
}
|
||||||
|
reader.readAsText(e);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
...mapMutations(['setLoadingStatus'])
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters(['getUserInfo'])
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'loadingManager.loading': {
|
||||||
|
handler: function (newValue) {
|
||||||
|
this.isHttpLoading = (newValue != null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vue.mixin(globalMixin);
|
||||||
@@ -0,0 +1,293 @@
|
|||||||
|
import projectConfig from '@/core/config';
|
||||||
|
import { buildGetUrl } from '@/core/http/requestUrl.js';
|
||||||
|
import { formatDate, parseDate } from 'element-ui/src/utils/date-util';
|
||||||
|
import { mapMutations } from 'vuex';
|
||||||
|
/**
|
||||||
|
* 上传文件组件相关方法
|
||||||
|
*/
|
||||||
|
const uploadMixin = {
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 解析返回的上传文件数据
|
||||||
|
* @param {String} jsonData 上传文件数据,[{name, downloadUri, filename}]
|
||||||
|
* @param {Object} params 上传文件的参数
|
||||||
|
* @returns {Array} 上传文件信息,[{name, downloadUri, filename, url}]
|
||||||
|
*/
|
||||||
|
parseUploadData (jsonData, params) {
|
||||||
|
let pathList = [];
|
||||||
|
if (jsonData != null) {
|
||||||
|
try {
|
||||||
|
pathList = JSON.parse(jsonData);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pathList.map((item) => {
|
||||||
|
let downloadParams = {...params};
|
||||||
|
downloadParams.filename = item.filename;
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
url: this.getUploadFileUrl(item, downloadParams)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 获得上传文件url列表
|
||||||
|
* @param {*} jsonData 上传文件数据,[{name, downloadUri, filename}]
|
||||||
|
* @param {*} params 上传文件的参数
|
||||||
|
* @returns {Array} 文件url列表
|
||||||
|
*/
|
||||||
|
getPictureList (jsonData, params) {
|
||||||
|
let tempList = this.parseUploadData(jsonData, params);
|
||||||
|
if (Array.isArray(tempList)) {
|
||||||
|
return tempList.map(item => item.url);
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 将选中文件信息格式化成json信息
|
||||||
|
* @param {Array} fileList 上传文件列表,[{name, fileUrl, data}]
|
||||||
|
*/
|
||||||
|
fileListToJson (fileList) {
|
||||||
|
if (Array.isArray(fileList)) {
|
||||||
|
return JSON.stringify(fileList.map((item) => {
|
||||||
|
return {
|
||||||
|
name: item.name,
|
||||||
|
downloadUri: item.downloadUri || item.response.data.downloadUri,
|
||||||
|
filename: item.filename || item.response.data.filename
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 获得上传文件url
|
||||||
|
* @param {*} item 上传文件
|
||||||
|
* @param {*} params 上传文件的参数
|
||||||
|
*/
|
||||||
|
getUploadFileUrl (item, params) {
|
||||||
|
if (item == null || item.downloadUri == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
let menuIdJsonStr = window.sessionStorage.getItem('currentMenuId');
|
||||||
|
let currentMenuId;
|
||||||
|
if (menuIdJsonStr != null) {
|
||||||
|
currentMenuId = (JSON.parse(menuIdJsonStr) || {}).data;
|
||||||
|
}
|
||||||
|
params.Authorization = window.sessionStorage.getItem('token');
|
||||||
|
params.MenuId = currentMenuId;
|
||||||
|
return buildGetUrl(item.downloadUri, params);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 获得上传接口
|
||||||
|
* @param {*} url 上传路径
|
||||||
|
*/
|
||||||
|
getUploadActionUrl (url) {
|
||||||
|
if (url != null && url[0] === '/') {
|
||||||
|
url = url.substr(1);
|
||||||
|
}
|
||||||
|
return projectConfig.baseUrl + url;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 上传文件是否图片文件
|
||||||
|
* @param {*} file 上传文件
|
||||||
|
*/
|
||||||
|
pictureFile (file) {
|
||||||
|
if (['image/jpeg', 'image/jpg', 'image/png'].indexOf(file.type) !== -1) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
this.$message.error('图片文件格式不正确,请重新选择');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
getUploadHeaders () {
|
||||||
|
let token = window.sessionStorage.getItem('token');
|
||||||
|
return {
|
||||||
|
Authorization: token
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const allowStatsType = [
|
||||||
|
'time',
|
||||||
|
'datetime',
|
||||||
|
'day',
|
||||||
|
'month',
|
||||||
|
'year'
|
||||||
|
];
|
||||||
|
/**
|
||||||
|
* 日期相关方法
|
||||||
|
*/
|
||||||
|
const statsDateRangeMixin = {
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 根据输入的日期获得日期范围(例如:输入2019-12-12,输出['2019-12-12 00:00:00', '2019-12-12 23:59:59'])
|
||||||
|
* @param {Date|String} date 要转换的日期
|
||||||
|
* @param {String} statsType 转换类型(day, month, year)
|
||||||
|
* @param {String} format 输出格式
|
||||||
|
*/
|
||||||
|
getDateRangeFilter (date, statsType = 'day', format = 'yyyy-MM-dd HH:mm:ss') {
|
||||||
|
if (date == null) return [];
|
||||||
|
|
||||||
|
statsType = allowStatsType.indexOf(statsType) === -1 ? 'day' : statsType;
|
||||||
|
date = date.substr(0, date.indexOf(' '));
|
||||||
|
let tempList = date.split('-');
|
||||||
|
let year = Number.parseInt(tempList[0]);
|
||||||
|
let month = Number.parseInt(tempList[1]);
|
||||||
|
let day = Number.parseInt(tempList[2]);
|
||||||
|
if (isNaN(year) || isNaN(month) || isNaN(day)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
let tempDate = new Date(year, month - 1, day);
|
||||||
|
// 判断是否正确的日期
|
||||||
|
if (isNaN(tempDate.getTime())) return [];
|
||||||
|
|
||||||
|
tempDate.setHours(0, 0, 0, 0);
|
||||||
|
let retDate;
|
||||||
|
switch (statsType) {
|
||||||
|
case 'day':
|
||||||
|
retDate = [
|
||||||
|
new Date(tempDate),
|
||||||
|
new Date(tempDate.setDate(tempDate.getDate() + 1))
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
case 'month':
|
||||||
|
tempDate.setDate(1);
|
||||||
|
retDate = [
|
||||||
|
new Date(tempDate),
|
||||||
|
new Date(tempDate.setMonth(tempDate.getMonth() + 1))
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
case 'year':
|
||||||
|
tempDate.setDate(1);
|
||||||
|
tempDate.setMonth(0);
|
||||||
|
retDate = [
|
||||||
|
new Date(tempDate),
|
||||||
|
new Date(tempDate.setFullYear(tempDate.getFullYear() + 1))
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
retDate[1] = new Date(retDate[1].getTime() - 1);
|
||||||
|
|
||||||
|
return [
|
||||||
|
formatDate(retDate[0], format),
|
||||||
|
formatDate(retDate[1], format)
|
||||||
|
];
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 格式化日期
|
||||||
|
* @param {Date|String} date 要格式化的日期
|
||||||
|
* @param {String} statsType 输出日期类型
|
||||||
|
* @param {String} format 输入日期的格式
|
||||||
|
*/
|
||||||
|
formatDateByStatsType (date, statsType = 'day', format = 'yyyy-MM-dd') {
|
||||||
|
if (date == null) return undefined;
|
||||||
|
statsType = allowStatsType.indexOf(statsType) === -1 ? 'day' : statsType;
|
||||||
|
if (statsType === 'datetime') format = 'yyyy-MM-dd HH:mm:ss';
|
||||||
|
|
||||||
|
let tempDate = ((date instanceof Date) ? date : parseDate(date, format));
|
||||||
|
if (!tempDate) return undefined;
|
||||||
|
switch (statsType) {
|
||||||
|
case 'time':
|
||||||
|
return formatDate(tempDate, 'HH:mm:ss');
|
||||||
|
case 'datetime':
|
||||||
|
return formatDate(tempDate, 'yyyy-MM-dd HH:mm:ss');
|
||||||
|
case 'day':
|
||||||
|
return formatDate(tempDate, 'yyyy-MM-dd');
|
||||||
|
case 'month':
|
||||||
|
return formatDate(tempDate, 'yyyy-MM');
|
||||||
|
case 'year':
|
||||||
|
return formatDate(tempDate, 'yyyy');
|
||||||
|
default:
|
||||||
|
return formatDate(tempDate, 'yyyy-MM-dd');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 获得统计类型中文名称
|
||||||
|
* @param {String} statsType 统计类型(day, month, year)
|
||||||
|
*/
|
||||||
|
getStatsTypeShowName (statsType) {
|
||||||
|
statsType = allowStatsType.indexOf(statsType) === -1 ? 'day' : statsType;
|
||||||
|
switch (statsType) {
|
||||||
|
case 'day': return '日统计';
|
||||||
|
case 'month': return '月统计';
|
||||||
|
case 'year': return '年统计';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 获取统计类型字典列表
|
||||||
|
* @param {Array} statsTypeList 统计类型列表
|
||||||
|
*/
|
||||||
|
getAllowStatsTypeList (statsTypeList) {
|
||||||
|
if (Array.isArray(statsTypeList) && statsTypeList.length > 0) {
|
||||||
|
return statsTypeList.map((item) => {
|
||||||
|
return {
|
||||||
|
id: item,
|
||||||
|
name: this.getStatsTypeShowName(item)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 页面缓存相关方法
|
||||||
|
*/
|
||||||
|
const cachePageMixin = {
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 移除缓存页面
|
||||||
|
* @param {*} name 缓存组件的名称
|
||||||
|
*/
|
||||||
|
removeCachePage (name) {
|
||||||
|
this.removeCachePage(name);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 从跳转页面返回并且刷新当前页面时调用
|
||||||
|
*/
|
||||||
|
onResume () {
|
||||||
|
},
|
||||||
|
...mapMutations(['addCachePage', 'removeCachePage'])
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.addCachePage(this.$options.name);
|
||||||
|
},
|
||||||
|
activated () {
|
||||||
|
if (this.$route && this.$route.meta && this.$route.meta.refresh) {
|
||||||
|
this.onResume();
|
||||||
|
this.$route.meta.refresh = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 缓存页面跳转页面相关方法
|
||||||
|
*/
|
||||||
|
const cachedPageChildMixin = {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
// 是否刷新父页面
|
||||||
|
refreshParentCachedPage: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeRouteLeave (to, from, next) {
|
||||||
|
if (to.meta == null) to.meta = {};
|
||||||
|
to.meta.refresh = this.refreshParentCachedPage;
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
uploadMixin,
|
||||||
|
statsDateRangeMixin,
|
||||||
|
cachePageMixin,
|
||||||
|
cachedPageChildMixin
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import '@/core/http';
|
||||||
|
import '@/components/Dialog';
|
||||||
|
import Vue from 'vue';
|
||||||
|
import ElementUI from 'element-ui';
|
||||||
|
// import 'element-ui/lib/theme-chalk/index.css'
|
||||||
|
import '@/assets/style/index.scss';
|
||||||
|
import '@/core/mixins/global.js';
|
||||||
|
import App from './App';
|
||||||
|
import router from './router';
|
||||||
|
import store from './store';
|
||||||
|
import TreeSelect from '@/components/TreeSelect';
|
||||||
|
import RichEditor from '@/components/RichEditor';
|
||||||
|
import InputNumberRange from '@/components/InputNumberRange';
|
||||||
|
import DateRange from '@/components/DateRange';
|
||||||
|
import FilterBox from '@/components/FilterBox';
|
||||||
|
import TableProgressColumn from '@/components/TableProgressColumn';
|
||||||
|
import VCharts from 'v-charts';
|
||||||
|
|
||||||
|
Vue.component('tree-select', TreeSelect);
|
||||||
|
Vue.component('rich-editor', RichEditor);
|
||||||
|
Vue.component('input-number-range', InputNumberRange);
|
||||||
|
Vue.component('date-range', DateRange);
|
||||||
|
Vue.component('filter-box', FilterBox);
|
||||||
|
Vue.component('table-progress-column', TableProgressColumn);
|
||||||
|
|
||||||
|
Vue.use(ElementUI);
|
||||||
|
Vue.use(VCharts);
|
||||||
|
|
||||||
|
Vue.config.productionTip = false;
|
||||||
|
|
||||||
|
/* eslint-disable no-new */
|
||||||
|
new Vue({
|
||||||
|
router,
|
||||||
|
store,
|
||||||
|
render: h => h(App)
|
||||||
|
}).$mount('#app');
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
|
|
||||||
|
import { register } from 'register-service-worker'
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV === 'production') {
|
||||||
|
register(`${process.env.BASE_URL}service-worker.js`, {
|
||||||
|
ready () {
|
||||||
|
console.log(
|
||||||
|
'App is being served from cache by a service worker.\n' +
|
||||||
|
'For more details, visit https://goo.gl/AFskqB'
|
||||||
|
)
|
||||||
|
},
|
||||||
|
registered () {
|
||||||
|
console.log('Service worker has been registered.')
|
||||||
|
},
|
||||||
|
cached () {
|
||||||
|
console.log('Content has been cached for offline use.')
|
||||||
|
},
|
||||||
|
updatefound () {
|
||||||
|
console.log('New content is downloading.')
|
||||||
|
},
|
||||||
|
updated () {
|
||||||
|
console.log('New content is available; please refresh.')
|
||||||
|
},
|
||||||
|
offline () {
|
||||||
|
console.log('No internet connection found. App is running in offline mode.')
|
||||||
|
},
|
||||||
|
error (error) {
|
||||||
|
console.error('Error during service worker registration:', error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
module.exports = file => require('../views/' + file + '.vue').default
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
module.exports = file => () => import('../views/' + file + '.vue')
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import Vue from 'vue';
|
||||||
|
import Router from 'vue-router';
|
||||||
|
import routers from './systemRouters.js';
|
||||||
|
import dialog from '@/components/Dialog';
|
||||||
|
|
||||||
|
Vue.use(Router)
|
||||||
|
|
||||||
|
const router = new Router({
|
||||||
|
mode: 'hash',
|
||||||
|
routes: routers
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路由跳转的时候判断token是否存在
|
||||||
|
*/
|
||||||
|
router.beforeResolve((to, from, next) => {
|
||||||
|
if (to.name === 'login') {
|
||||||
|
next();
|
||||||
|
} else {
|
||||||
|
let token = sessionStorage.getItem('token');
|
||||||
|
if (!token || !/\S/.test(token)) {
|
||||||
|
dialog.closeAll();
|
||||||
|
next({ name: 'login' })
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
// 开发环境不使用懒加载, 因为懒加载页面太多的话会造成webpack热更新太慢, 所以只有开发环境使用懒加载
|
||||||
|
const _import = require('./import-' + process.env.NODE_ENV)
|
||||||
|
|
||||||
|
function getProps (route) {
|
||||||
|
return route.query;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 系统生成路由
|
||||||
|
const routers = [
|
||||||
|
{ path: '/login', component: _import('login/index'), name: 'login', props: getProps, desc: '登录' },
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
component: _import('layout/index'),
|
||||||
|
name: 'main',
|
||||||
|
props: getProps,
|
||||||
|
redirect: {
|
||||||
|
name: 'welcome'
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
title: '主页',
|
||||||
|
showOnly: true
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{path: 'welcome', component: _import('welcome/index'), name: 'welcome', meta: {title: '欢迎'}},
|
||||||
|
{path: 'formUaaUser', component: _import('generated/formUaaUser/index'), name: 'formUaaUser', props: getProps, meta: {title: '用户管理'}},
|
||||||
|
{path: 'formAuthClient', component: _import('generated/formAuthClient/index'), name: 'formAuthClient', props: getProps, meta: {title: '应用管理'}},
|
||||||
|
{path: 'formUaaOperator', component: _import('generated/formUaaOperator/index'), name: 'formUaaOperator', props: getProps, meta: {title: '操作员管理'}}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
export default routers;
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/**
|
||||||
|
* 常量字典数据
|
||||||
|
*/
|
||||||
|
import Vue from 'vue';
|
||||||
|
|
||||||
|
class DictionaryBase extends Map {
|
||||||
|
constructor (dataList, keyId = 'id', symbolId = 'symbol') {
|
||||||
|
super();
|
||||||
|
this.setList(dataList, keyId, symbolId);
|
||||||
|
}
|
||||||
|
|
||||||
|
setList (dataList, keyId = 'id', symbolId = 'symbol') {
|
||||||
|
this.clear();
|
||||||
|
if (Array.isArray(dataList)) {
|
||||||
|
dataList.forEach((item) => {
|
||||||
|
this.set(item[keyId], item);
|
||||||
|
if (item[symbolId] != null) {
|
||||||
|
Object.defineProperty(this, item[symbolId], {
|
||||||
|
get: function () {
|
||||||
|
return item[keyId];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getList (valueId = 'name', parentIdKey = 'parentId', filter) {
|
||||||
|
let temp = [];
|
||||||
|
this.forEach((value, key) => {
|
||||||
|
let obj = {
|
||||||
|
id: key,
|
||||||
|
name: (typeof value === 'string') ? value : value[valueId],
|
||||||
|
parentId: value[parentIdKey]
|
||||||
|
};
|
||||||
|
if (typeof filter !== 'function' || filter(obj)) {
|
||||||
|
temp.push(obj);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
getValue (id, valueId = 'name') {
|
||||||
|
return (this.get(id) || {})[valueId];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const UserStatus = new DictionaryBase([
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
name: '正常',
|
||||||
|
symbol: 'USED'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: '锁定',
|
||||||
|
symbol: 'LOCKED'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
Vue.prototype.UserStatus = UserStatus;
|
||||||
|
|
||||||
|
const UserType = new DictionaryBase([
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
name: '管理员',
|
||||||
|
symbol: 'ADMIN'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: '普通操作员',
|
||||||
|
symbol: 'NORMAL'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
Vue.prototype.UserType = UserType;
|
||||||
|
|
||||||
|
export {
|
||||||
|
DictionaryBase,
|
||||||
|
UserStatus,
|
||||||
|
UserType
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export default {}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import { findMenuItem } from './utils';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
getCollapse: (state) => {
|
||||||
|
return state.isCollapse;
|
||||||
|
},
|
||||||
|
getClientHeight: (state) => {
|
||||||
|
return state.documentClientHeight;
|
||||||
|
},
|
||||||
|
getUserInfo: (state) => {
|
||||||
|
return state.userInfo;
|
||||||
|
},
|
||||||
|
getCachePages: (state) => {
|
||||||
|
return state.cachePages;
|
||||||
|
},
|
||||||
|
getTagList: (state) => {
|
||||||
|
return state.tagList;
|
||||||
|
},
|
||||||
|
getMenuList: (state) => {
|
||||||
|
return state.menuList;
|
||||||
|
},
|
||||||
|
getCurrentMenuId: (state) => {
|
||||||
|
return state.currentMenuId;
|
||||||
|
},
|
||||||
|
getMenuItem: (state) => {
|
||||||
|
if (Array.isArray(state.menuList)) {
|
||||||
|
for (let i = 0; i < state.menuList.length; i++) {
|
||||||
|
let temp = findMenuItem(state.menuList[i], state.currentMenuId);
|
||||||
|
if (temp != null) return temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
getCurrentMenuPath: (state) => {
|
||||||
|
let menuPath = [];
|
||||||
|
if (Array.isArray(state.menuList)) {
|
||||||
|
for (let i = 0; i < state.menuList.length; i++) {
|
||||||
|
let temp = findMenuItem(state.menuList[i], state.currentMenuId, menuPath);
|
||||||
|
if (temp != null) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return menuPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import Vue from 'vue';
|
||||||
|
import Vuex from 'vuex';
|
||||||
|
import state from './state.js';
|
||||||
|
import getters from './getters.js';
|
||||||
|
import mutations from './mutations.js';
|
||||||
|
import actions from './actions.js';
|
||||||
|
|
||||||
|
Vue.use(Vuex);
|
||||||
|
export default new Vuex.Store({
|
||||||
|
state,
|
||||||
|
getters,
|
||||||
|
mutations,
|
||||||
|
actions,
|
||||||
|
strict: process.env.NODE_ENV !== 'production'
|
||||||
|
});
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
import { initUserInfo, findMenuItem } from './utils';
|
||||||
|
import { setObjectToSessionStorage, findItemFromList, treeDataTranslate } from '@/utils';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setCollapse: (state, isCollapse) => {
|
||||||
|
state.isCollapse = isCollapse;
|
||||||
|
},
|
||||||
|
setClientHeight: (state, height) => {
|
||||||
|
state.documentClientHeight = height;
|
||||||
|
},
|
||||||
|
setUserInfo: (state, info) => {
|
||||||
|
setObjectToSessionStorage('userInfo', info);
|
||||||
|
state.userInfo = initUserInfo(info);
|
||||||
|
},
|
||||||
|
addCachePage (state, name) {
|
||||||
|
if (state.cachePages.indexOf(name) === -1) {
|
||||||
|
let temp = [...state.cachePages];
|
||||||
|
temp.push(name);
|
||||||
|
setObjectToSessionStorage('cachePages', temp);
|
||||||
|
state.cachePages = temp;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
removeCachePage (state, name) {
|
||||||
|
let pos = state.cachePages.indexOf(name);
|
||||||
|
if (pos !== -1) {
|
||||||
|
let temp = [...state.cachePages];
|
||||||
|
temp.splice(pos, 1);
|
||||||
|
setObjectToSessionStorage('cachePages', temp);
|
||||||
|
state.cachePages = temp;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clearCachePage (state) {
|
||||||
|
setObjectToSessionStorage('cachePages', []);
|
||||||
|
state.cachePages = [];
|
||||||
|
},
|
||||||
|
addTag (state, id) {
|
||||||
|
if (id == null || id === '') return;
|
||||||
|
// 新增的标签是否存在
|
||||||
|
let tagList = state.tagList;
|
||||||
|
let tagItem = null;
|
||||||
|
if (Array.isArray(tagList)) {
|
||||||
|
tagItem = findItemFromList(tagList, id, 'menuId');
|
||||||
|
}
|
||||||
|
if (tagItem != null) return;
|
||||||
|
// 添加新增标签以及更新页面缓存
|
||||||
|
let menuList = state.menuList;
|
||||||
|
let menuObject = null;
|
||||||
|
if (Array.isArray(menuList)) {
|
||||||
|
for (let i = 0; i < menuList.length; i++) {
|
||||||
|
menuObject = findMenuItem(menuList[i], id);
|
||||||
|
if (menuObject != null) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (menuObject != null) {
|
||||||
|
state.tagList = [...state.tagList, menuObject];
|
||||||
|
if (Array.isArray(state.cachePages) && state.cachePages.indexOf(menuObject.formRouterName) === -1) {
|
||||||
|
state.cachePages = [...state.cachePages, menuObject.formRouterName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setObjectToSessionStorage('cachePages', state.cachePages);
|
||||||
|
setObjectToSessionStorage('tagList', state.tagList);
|
||||||
|
},
|
||||||
|
removeTag (state, id) {
|
||||||
|
if (id == null || id === '') return;
|
||||||
|
// 移除标签
|
||||||
|
let nextPos = -1;
|
||||||
|
let tagItem = null;
|
||||||
|
for (let i = 0; i < state.tagList.length; i++) {
|
||||||
|
if (state.tagList[i].menuId === id) {
|
||||||
|
tagItem = state.tagList[i];
|
||||||
|
state.tagList.splice(i, 1);
|
||||||
|
nextPos = Math.min(i, state.tagList.length - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// let tagItem = findItemFromList(state.tagList, id, 'menuId', true);
|
||||||
|
if (tagItem == null) return;
|
||||||
|
// 移除页面缓存
|
||||||
|
findItemFromList(state.cachePages, tagItem.formRouterName, undefined, true);
|
||||||
|
setObjectToSessionStorage('cachePages', state.cachePages);
|
||||||
|
setObjectToSessionStorage('tagList', state.tagList);
|
||||||
|
// 如果移除的是当前显示页面,重新选择显示页面
|
||||||
|
let showTag = null;
|
||||||
|
if (state.currentMenuId === id) {
|
||||||
|
showTag = state.tagList[nextPos];
|
||||||
|
let tempId = (showTag || {}).menuId;
|
||||||
|
if (setObjectToSessionStorage('currentMenuId', tempId)) state.currentMenuId = tempId;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
closeOtherTags (state, id) {
|
||||||
|
if (id == null || id === '') return;
|
||||||
|
// 移除其他所有标签
|
||||||
|
if (Array.isArray(state.tagList)) {
|
||||||
|
state.tagList = state.tagList.filter((item) => {
|
||||||
|
return item.menuId === id;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let menuObject = state.tagList[0];
|
||||||
|
if (menuObject && menuObject.formRouterName && menuObject.formRouterName !== '') {
|
||||||
|
state.cachePages = [menuObject.formRouterName];
|
||||||
|
if (setObjectToSessionStorage('currentMenuId', menuObject.menuId)) state.currentMenuId = menuObject.menuId;
|
||||||
|
}
|
||||||
|
setObjectToSessionStorage('cachePages', state.cachePages);
|
||||||
|
setObjectToSessionStorage('tagList', state.tagList);
|
||||||
|
},
|
||||||
|
clearAllTags (state) {
|
||||||
|
if (setObjectToSessionStorage('currentMenuId', undefined)) state.currentMenuId = undefined;
|
||||||
|
if (setObjectToSessionStorage('cachePages', [])) state.cachePages = [];
|
||||||
|
if (setObjectToSessionStorage('tagList', [])) state.tagList = [];
|
||||||
|
},
|
||||||
|
setMenuList: (state, list) => {
|
||||||
|
if (Array.isArray(list)) {
|
||||||
|
if (setObjectToSessionStorage('menuList', list)) state.menuList = treeDataTranslate(list, 'menuId', 'parentId');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setCurrentMenuId: (state, menuId) => {
|
||||||
|
let menuItem = null;
|
||||||
|
if (setObjectToSessionStorage('currentMenuId', menuId)) state.currentMenuId = menuId;
|
||||||
|
if (Array.isArray(state.tagList) && Array.isArray(state.menuList)) {
|
||||||
|
for (let i = 0; i < state.menuList.length; i++) {
|
||||||
|
menuItem = findMenuItem(state.menuList[i], menuId, 'menuId');
|
||||||
|
if (menuItem != null) {
|
||||||
|
// 添加新的tag
|
||||||
|
let tagItem = findItemFromList(state.tagList, menuId, 'menuId');
|
||||||
|
if (tagItem == null) {
|
||||||
|
state.tagList = [...state.tagList, menuItem];
|
||||||
|
setObjectToSessionStorage('tagList', state.tagList);
|
||||||
|
}
|
||||||
|
// 添加新缓存
|
||||||
|
if (Array.isArray(state.cachePages) && state.cachePages.indexOf(menuItem.formRouterName) === -1) {
|
||||||
|
state.cachePages = [...state.cachePages, menuItem.formRouterName];
|
||||||
|
setObjectToSessionStorage('cachePages', state.cachePages);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { initUserInfo } from './utils';
|
||||||
|
import { getObjectFromSessionStorage, treeDataTranslate } from '@/utils';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// 是否左侧菜单折叠
|
||||||
|
isCollapse: false,
|
||||||
|
// 浏览器客户区高度
|
||||||
|
documentClientHeight: 100,
|
||||||
|
// 用户登录信息
|
||||||
|
userInfo: initUserInfo(),
|
||||||
|
// 缓存页面
|
||||||
|
cachePages: getObjectFromSessionStorage('cachePages', []),
|
||||||
|
// 当前标签
|
||||||
|
tagList: getObjectFromSessionStorage('tagList', []),
|
||||||
|
// 菜单列表
|
||||||
|
menuList: treeDataTranslate(getObjectFromSessionStorage('menuList', []), 'menuId', 'parentId'),
|
||||||
|
// 当前菜单
|
||||||
|
currentMenuId: getObjectFromSessionStorage('currentMenuId', undefined)
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { getObjectFromSessionStorage } from '@/utils';
|
||||||
|
|
||||||
|
function findMenuItem (menuItem, menuId, path) {
|
||||||
|
if (Array.isArray(path)) path.push(menuItem);
|
||||||
|
if ((menuItem.menuId + '') === (menuId + '')) return menuItem;
|
||||||
|
|
||||||
|
let bFind = false;
|
||||||
|
let findItem = null;
|
||||||
|
if (Array.isArray(menuItem.children)) {
|
||||||
|
for (let i = 0; i < menuItem.children.length; i++) {
|
||||||
|
findItem = findMenuItem(menuItem.children[i], menuId, path);
|
||||||
|
if (findItem != null) {
|
||||||
|
bFind = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bFind && Array.isArray(path)) path.pop();
|
||||||
|
return bFind ? findItem : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initUserInfo (userInfo) {
|
||||||
|
if (userInfo == null) userInfo = getObjectFromSessionStorage('userInfo');
|
||||||
|
|
||||||
|
if (userInfo != null && userInfo.permCodeList != null && Array.isArray(userInfo.permCodeList)) {
|
||||||
|
userInfo.permCodeSet = new Set(userInfo.permCodeList);
|
||||||
|
}
|
||||||
|
|
||||||
|
return userInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
findMenuItem,
|
||||||
|
initUserInfo
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
const defaultLineChartOption = {
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '20px',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
axisLabel: {
|
||||||
|
interval: 0,
|
||||||
|
showMaxLabel: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
top: '3%'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultBarChartOption = {
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '20px',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
axisLabel: {
|
||||||
|
interval: 0,
|
||||||
|
showMaxLabel: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
top: '3%'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultPieChartOption = {
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '20px',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
top: '3%'
|
||||||
|
},
|
||||||
|
series: {
|
||||||
|
center: ['50%', '60%']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
defaultLineChartOption,
|
||||||
|
defaultBarChartOption,
|
||||||
|
defaultPieChartOption
|
||||||
|
}
|
||||||
@@ -0,0 +1,222 @@
|
|||||||
|
import JSEncrypt from 'jsencrypt';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 列表数据转换树形数据
|
||||||
|
* @param {Array} data 要转换的列表
|
||||||
|
* @param {String} id 主键字段字段名
|
||||||
|
* @param {String} pid 父字段字段名
|
||||||
|
* @returns {Array} 转换后的树数据
|
||||||
|
*/
|
||||||
|
export function treeDataTranslate (data, id = 'id', pid = 'parentId') {
|
||||||
|
var res = []
|
||||||
|
var temp = {}
|
||||||
|
for (var i = 0; i < data.length; i++) {
|
||||||
|
temp[data[i][id]] = data[i]
|
||||||
|
}
|
||||||
|
for (var k = 0; k < data.length; k++) {
|
||||||
|
if (temp[data[k][pid]] && data[k][id] !== data[k][pid]) {
|
||||||
|
if (!temp[data[k][pid]]['children']) {
|
||||||
|
temp[data[k][pid]]['children'] = []
|
||||||
|
}
|
||||||
|
if (!temp[data[k][pid]]['_level']) {
|
||||||
|
temp[data[k][pid]]['_level'] = 1
|
||||||
|
}
|
||||||
|
data[k]['_level'] = temp[data[k][pid]]._level + 1
|
||||||
|
data[k]['_parent'] = data[k][pid]
|
||||||
|
temp[data[k][pid]]['children'].push(data[k])
|
||||||
|
} else {
|
||||||
|
res.push(data[k])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 获取字符串字节长度(中文算2个字符)
|
||||||
|
* @param {String} str 要获取长度的字符串
|
||||||
|
*/
|
||||||
|
export function getStringLength (str) {
|
||||||
|
return str.replace(/[\u4e00-\u9fa5\uff00-\uffff]/g, '**').length
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 获取uuid
|
||||||
|
*/
|
||||||
|
export function getUUID () {
|
||||||
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
||||||
|
return (c === 'x' ? (Math.random() * 16 | 0) : ('r&0x3' | '0x8')).toString(16)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 大小驼峰变换函数
|
||||||
|
* @param name 要转换的字符串
|
||||||
|
* @param type 转换的类型0:转换成小驼峰,1:转换成大驼峰
|
||||||
|
*/
|
||||||
|
export function nameTranslate (name, type) {
|
||||||
|
name = name.toLowerCase();
|
||||||
|
let nameArray = name.split('_');
|
||||||
|
nameArray.forEach((item, index) => {
|
||||||
|
if (index === 0) {
|
||||||
|
name = type === 1 ? item.slice(0, 1).toUpperCase() + item.slice(1) : item;
|
||||||
|
} else {
|
||||||
|
name = name + item.slice(0, 1).toUpperCase() + item.slice(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
nameArray = name.split('-');
|
||||||
|
nameArray.forEach((item, index) => {
|
||||||
|
if (index === 0) {
|
||||||
|
name = type === 1 ? item.slice(0, 1).toUpperCase() + item.slice(1) : item;
|
||||||
|
} else {
|
||||||
|
name = name + item.slice(0, 1).toUpperCase() + item.slice(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 通过id从树中获取指定的节点
|
||||||
|
* @param {Object} node 根节点
|
||||||
|
* @param {String|Nubmer} id 键值
|
||||||
|
* @param {Array} list 保存查询路径
|
||||||
|
* @param {String} idKey 主键字段名
|
||||||
|
* @param {String} childKey 子节点字段名
|
||||||
|
*/
|
||||||
|
function findNode (node, id, list, idKey = 'id', childKey = 'children') {
|
||||||
|
if (Array.isArray(list)) list.push(node[idKey]);
|
||||||
|
if (node[idKey] === id) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node[childKey] != null && Array.isArray(node[childKey])) {
|
||||||
|
for (let i = 0; i < node[childKey].length; i++) {
|
||||||
|
let tempNode = findNode(node[childKey][i], id, list, idKey, childKey);
|
||||||
|
if (tempNode) return tempNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(list)) list.pop();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 通过id返回从根节点到指定节点的路径
|
||||||
|
* @param {Array} treeRoot 树根节点数组
|
||||||
|
* @param {*} id 要查询的节点的id
|
||||||
|
* @param {*} idKey 主键字段名
|
||||||
|
* @param {*} childKey 子节点字段名
|
||||||
|
*/
|
||||||
|
export function findTreeNodePath (treeRoot, id, idKey = 'id', childKey = 'children') {
|
||||||
|
let tempList = [];
|
||||||
|
for (let i = 0; i < treeRoot.length; i++) {
|
||||||
|
if (findNode(treeRoot[i], id, tempList, idKey, childKey)) {
|
||||||
|
return tempList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 通过id从树中查找节点
|
||||||
|
* @param {Array} treeRoot 根节点数组
|
||||||
|
* @param {*} id 要查找的节点的id
|
||||||
|
* @param {*} idKey 主键字段名
|
||||||
|
* @param {*} childKey 子节点字段名
|
||||||
|
*/
|
||||||
|
export function findTreeNode (treeRoot, id, idKey = 'id', childKey = 'children') {
|
||||||
|
for (let i = 0; i < treeRoot.length; i++) {
|
||||||
|
let tempNode = findNode(treeRoot[i], id, undefined, idKey, childKey);
|
||||||
|
if (tempNode) return tempNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 把Object转换成query字符串
|
||||||
|
* @param {Object} params 要转换的Object
|
||||||
|
*/
|
||||||
|
export function objectToQueryString (params) {
|
||||||
|
if (params == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return Object.keys(params).map((key) => {
|
||||||
|
return `${key}=${params[key]}`;
|
||||||
|
}).join('&');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 从数组中查找某一项
|
||||||
|
* @param {Array} list 要查找的数组
|
||||||
|
* @param {String} id 要查找的节点id
|
||||||
|
* @param {String} idKey 主键字段名(如果为null则直接比较)
|
||||||
|
* @param {Boolean} removeItem 是否从数组中移除查找到的节点
|
||||||
|
* @returns {Object} 找到返回节点,没找到返回undefined
|
||||||
|
*/
|
||||||
|
export function findItemFromList (list, id, idKey, removeItem = false) {
|
||||||
|
if (Array.isArray(list) && list.length > 0 && id != null) {
|
||||||
|
for (let i = 0; i < list.length; i++) {
|
||||||
|
let item = list[i];
|
||||||
|
if (((idKey == null || idKey === '') && item === id) || (idKey != null && item[idKey] === id)) {
|
||||||
|
if (removeItem) list.splice(i, 1);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 将数据保存到sessionStorage
|
||||||
|
* @param {*} key sessionStorage的键值
|
||||||
|
* @param {*} value 要保存的数据
|
||||||
|
*/
|
||||||
|
export function setObjectToSessionStorage (key, value) {
|
||||||
|
if (key == null || key === '') return false;
|
||||||
|
if (value == null) {
|
||||||
|
window.sessionStorage.removeItem(key);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
let jsonObj = {
|
||||||
|
data: value
|
||||||
|
}
|
||||||
|
window.sessionStorage.setItem(key, JSON.stringify(jsonObj));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 从sessionStorage里面获取数据
|
||||||
|
* @param {String} key 键值
|
||||||
|
* @param {*} defaultValue 默认值
|
||||||
|
*/
|
||||||
|
export function getObjectFromSessionStorage (key, defaultValue) {
|
||||||
|
let jsonObj = null;
|
||||||
|
try {
|
||||||
|
jsonObj = JSON.parse(window.sessionStorage.getItem(key));
|
||||||
|
jsonObj = (jsonObj || {}).data;
|
||||||
|
} catch (e) {
|
||||||
|
jsonObj = defaultValue;
|
||||||
|
};
|
||||||
|
return (jsonObj != null) ? jsonObj : defaultValue;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 判读字符串是否一个数字
|
||||||
|
* @param {String} str 要判断的字符串
|
||||||
|
*/
|
||||||
|
export function isNumber (str) {
|
||||||
|
let num = Number.parseFloat(str);
|
||||||
|
if (Number.isNaN(num)) return false;
|
||||||
|
return num.toString() === str;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 生成随机数
|
||||||
|
* @param {Integer} min 随机数最小值
|
||||||
|
* @param {Integer} max 随机数最大值
|
||||||
|
*/
|
||||||
|
export function random (min, max) {
|
||||||
|
let base = Math.random();
|
||||||
|
return min + base * (max - min);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 加密
|
||||||
|
* @param {*} value 要加密的字符串
|
||||||
|
*/
|
||||||
|
const publicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpC4QMnbTrQOFriJJCCFFWhlruBJThAEBfRk7pRx1jsAhyNVL3CqJb0tRvpnbCnJhrRAEPdgFHXv5A0RrvFp+5Cw7QoFH6O9rKB8+0H7+aVQeKITMUHf/XMXioymw6Iq4QfWd8RhdtM1KM6eGTy8aU7SO2s69Mc1LXefg/x3yw6wIDAQAB';
|
||||||
|
export function encrypt (value) {
|
||||||
|
if (value == null || value === '') return null;
|
||||||
|
let encrypt = new JSEncrypt();
|
||||||
|
encrypt.setPublicKey(publicKey);
|
||||||
|
return encodeURIComponent(encrypt.encrypt(value));
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
const pattern = {
|
||||||
|
mobie: /^((\+?86)|(\(\+86\)))?(13[012356789][0-9]{8}|15[012356789][0-9]{8}|18[02356789][0-9]{8}|147[0-9]{8}|1349[0-9]{7})$/,
|
||||||
|
english: /^[a-zA-Z]+$/,
|
||||||
|
englishAndNumber: /^[a-zA-Z0-9]+$/
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮箱
|
||||||
|
* @param str
|
||||||
|
*/
|
||||||
|
export function isEmail (str) {
|
||||||
|
return /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/.test(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号码
|
||||||
|
* @param str
|
||||||
|
*/
|
||||||
|
export function isMobile (str) {
|
||||||
|
return pattern.mobie.test(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 电话号码
|
||||||
|
* @param str
|
||||||
|
*/
|
||||||
|
export function isPhone (str) {
|
||||||
|
return /^([0-9]{3,4}-)?[0-9]{7,8}$/.test(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
pattern
|
||||||
|
}
|
||||||
@@ -0,0 +1,297 @@
|
|||||||
|
import { Message } from 'element-ui';
|
||||||
|
import { treeDataTranslate } from '@/utils';
|
||||||
|
|
||||||
|
const DEFAULT_PAGE_SIZE = 10;
|
||||||
|
|
||||||
|
export class DropdownWidget {
|
||||||
|
/**
|
||||||
|
* 下拉组件(Select、Cascade、TreeSelect等)
|
||||||
|
* @param {function () : Promise} loadDropdownData 下拉数据获取函数
|
||||||
|
* @param {Boolean} isTree 是否是树数据
|
||||||
|
* @param {String} idKey 键字段字段名
|
||||||
|
* @param {String} parentIdKey 父字段字段名
|
||||||
|
*/
|
||||||
|
constructor (loadDropdownData, isTree = false, idKey = 'id', parentIdKey = 'parentId') {
|
||||||
|
this.loading = false;
|
||||||
|
this.dirty = true;
|
||||||
|
this.dropdownList = [];
|
||||||
|
this.isTree = isTree;
|
||||||
|
this.idKey = idKey;
|
||||||
|
this.parentIdKey = parentIdKey;
|
||||||
|
this.loadDropdownData = loadDropdownData;
|
||||||
|
this.setDropdownList = this.setDropdownList.bind(this);
|
||||||
|
this.onVisibleChange = this.onVisibleChange.bind(this);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 重新获取下拉数据
|
||||||
|
*/
|
||||||
|
reloadDropdownData () {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!this.loading) {
|
||||||
|
if (typeof this.loadDropdownData === 'function') {
|
||||||
|
this.loading = true;
|
||||||
|
this.loadDropdownData().then(dataList => {
|
||||||
|
this.setDropdownList(dataList);
|
||||||
|
this.loading = false;
|
||||||
|
this.dirty = false;
|
||||||
|
resolve(this.dropdownList);
|
||||||
|
}).catch(e => {
|
||||||
|
this.setDropdownList([]);
|
||||||
|
this.loading = false;
|
||||||
|
reject(this.dropdownList);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
reject(new Error('获取下拉数据失败'));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resolve(this.dropdownList);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 下拉框显示或隐藏时调用
|
||||||
|
* @param {Boolean} isShow 正在显示或者隐藏
|
||||||
|
*/
|
||||||
|
onVisibleChange (isShow) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (isShow && this.dirty && !this.loading) {
|
||||||
|
this.reloadDropdownData().then(res => {
|
||||||
|
resolve(res);
|
||||||
|
}).catch(e => {
|
||||||
|
reject(e);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
resolve(this.dropdownList);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 设置下拉数据
|
||||||
|
* @param {Array} dataList 要显示的下拉数据
|
||||||
|
*/
|
||||||
|
setDropdownList (dataList) {
|
||||||
|
if (Array.isArray(dataList)) {
|
||||||
|
this.dropdownList = this.isTree ? treeDataTranslate(dataList, this.idKey, this.parentIdKey) : dataList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TableWidget {
|
||||||
|
/**
|
||||||
|
* 表格组件
|
||||||
|
* @param {function (params: Object) : Promise} loadTableData 表数据获取函数
|
||||||
|
* @param {function () : Boolean} verifyTableParameter 表数据获取检验函数
|
||||||
|
* @param {Boolean} paged 是否支持分页
|
||||||
|
* @param {String} orderFieldName 默认排序字段
|
||||||
|
* @param {Boolean} ascending 默认排序方式(true为正序,false为倒序)
|
||||||
|
* @param {String} dateAggregateBy 默认排序字段的日期统计类型
|
||||||
|
*/
|
||||||
|
constructor (loadTableData, verifyTableParameter, paged, orderFieldName, ascending, dateAggregateBy) {
|
||||||
|
this.oldPage = 0;
|
||||||
|
this.currentPage = 1;
|
||||||
|
this.oldPageSize = DEFAULT_PAGE_SIZE;
|
||||||
|
this.pageSize = DEFAULT_PAGE_SIZE;
|
||||||
|
this.totalCount = 0;
|
||||||
|
this.dataList = [];
|
||||||
|
this.orderInfo = {
|
||||||
|
fieldName: orderFieldName,
|
||||||
|
asc: ascending,
|
||||||
|
dateAggregateBy: dateAggregateBy
|
||||||
|
};
|
||||||
|
this.paged = paged;
|
||||||
|
this.searchVerify = verifyTableParameter || function () { return true; };
|
||||||
|
this.loadTableData = loadTableData || function () { return Promise.resolve(); };
|
||||||
|
this.onCurrentPageChange = this.onCurrentPageChange.bind(this);
|
||||||
|
this.onPageSizeChange = this.onPageSizeChange.bind(this);
|
||||||
|
this.onSortChange = this.onSortChange.bind(this);
|
||||||
|
this.getTableIndex = this.getTableIndex.bind(this);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 表格分页变化
|
||||||
|
* @param {Integer} newCurrentPage 变化后的显示页面
|
||||||
|
*/
|
||||||
|
onCurrentPageChange (newCurrentPage) {
|
||||||
|
this.loadTableDataImpl(newCurrentPage, this.pageSize).then(() => {
|
||||||
|
this.oldPage = this.currentPage = newCurrentPage;
|
||||||
|
}).catch(() => {
|
||||||
|
this.currentPage = this.oldPage;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 表格分页每页显示数量变化
|
||||||
|
* @param {Integer} newPageSize 变化后的每页显示数量
|
||||||
|
*/
|
||||||
|
onPageSizeChange (newPageSize) {
|
||||||
|
this.loadTableDataImpl(1, newPageSize).then(() => {
|
||||||
|
this.oldPage = this.currentPage = 1;
|
||||||
|
this.oldPageSize = this.pageSize = newPageSize;
|
||||||
|
}).catch(e => {
|
||||||
|
this.currentPage = this.oldPage;
|
||||||
|
this.pageSize = this.oldPageSize;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 表格排序字段变化
|
||||||
|
* @param {String} prop 排序字段的字段名
|
||||||
|
* @param {String} order 正序还是倒序
|
||||||
|
*/
|
||||||
|
onSortChange ({ prop, order }) {
|
||||||
|
this.orderInfo.fieldName = prop;
|
||||||
|
this.orderInfo.asc = (order === 'ascending');
|
||||||
|
this.refreshTable();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 获取每一行的index信息
|
||||||
|
* @param {Integer} index 表格在本页位置
|
||||||
|
*/
|
||||||
|
getTableIndex (index) {
|
||||||
|
return this.paged ? ((this.currentPage - 1) * this.pageSize + (index + 1)) : (index + 1);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 获取表格数据
|
||||||
|
* @param {Integer} pageNum 当前分页
|
||||||
|
* @param {Integer} pageSize 每页数量
|
||||||
|
* @param {Boolean} reload 是否重新获取数据
|
||||||
|
*/
|
||||||
|
loadTableDataImpl (pageNum, pageSize, reload = false) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (typeof this.loadTableData !== 'function') {
|
||||||
|
reject();
|
||||||
|
} else {
|
||||||
|
// 如果pageSize和pageNum没有变化,并且不强制刷新
|
||||||
|
if (this.paged && !reload && this.oldPage === pageNum && this.oldPageSize === pageSize) {
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
let params = {};
|
||||||
|
if (this.orderInfo.fieldName != null) params.orderParam = [this.orderInfo];
|
||||||
|
if (this.paged) {
|
||||||
|
params.pageParam = {
|
||||||
|
pageNum,
|
||||||
|
pageSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.loadTableData(params).then(tableData => {
|
||||||
|
this.dataList = tableData.dataList;
|
||||||
|
this.totalCount = tableData.totalCount;
|
||||||
|
resolve();
|
||||||
|
}).catch(e => {
|
||||||
|
reject(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 刷新表格数据
|
||||||
|
* @param {Boolean} research 是否按照新的查询条件重新查询(调用verify函数)
|
||||||
|
* @param {Integer} pageNum 当前页面
|
||||||
|
*/
|
||||||
|
refreshTable (research = false, pageNum = undefined, showMsg = false) {
|
||||||
|
let reload = false;
|
||||||
|
if (research) {
|
||||||
|
if (typeof this.searchVerify === 'function' && !this.searchVerify()) return;
|
||||||
|
reload = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Number.isInteger(pageNum) && pageNum !== this.currentPage) {
|
||||||
|
this.loadTableDataImpl(pageNum, this.pageSize, reload).then(res => {
|
||||||
|
this.oldPage = this.currentPage = pageNum;
|
||||||
|
if (research && showMsg) Message.success('查询成功');
|
||||||
|
}).catch(e => {
|
||||||
|
this.currentPage = this.oldPage;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.loadTableDataImpl(this.currentPage, this.pageSize, true).catch(e => {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class UploadWidget {
|
||||||
|
/**
|
||||||
|
* 上传组件
|
||||||
|
* @param {Integer} maxCount 最大上传数量
|
||||||
|
*/
|
||||||
|
constructor (maxCount = 1) {
|
||||||
|
this.maxCount = maxCount;
|
||||||
|
this.fileList = [];
|
||||||
|
this.onFileChange = this.onFileChange.bind(this);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 上传文件列表改变
|
||||||
|
* @param {Object} file 改变的文件
|
||||||
|
* @param {Array} fileList 改变后的文件列表
|
||||||
|
*/
|
||||||
|
onFileChange (file, fileList) {
|
||||||
|
if (Array.isArray(fileList) && fileList.length > 0) {
|
||||||
|
if (this.maxCount === 1) {
|
||||||
|
this.fileList = [fileList[fileList.length - 1]];
|
||||||
|
} else {
|
||||||
|
this.fileList = fileList;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.fileList = [];
|
||||||
|
}
|
||||||
|
return this.fileList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ChartWidget {
|
||||||
|
/**
|
||||||
|
* 图表组件
|
||||||
|
* @param {function (params) : Promise} loadTableData chart数据获取函数
|
||||||
|
* @param {function () : Boolean} verifyTableParameter 数据参数检验函数
|
||||||
|
* @param {Array} columns 数据列
|
||||||
|
*/
|
||||||
|
constructor (loadTableData, verifyTableParameter, columns) {
|
||||||
|
this.columns = columns;
|
||||||
|
this.loading = false;
|
||||||
|
this.dataEmpty = false;
|
||||||
|
this.chartData = undefined;
|
||||||
|
this.chartObject = undefined;
|
||||||
|
this.dimensionMaps = new Map();
|
||||||
|
this.chartSetting = undefined;
|
||||||
|
this.searchVerify = verifyTableParameter || function () { return true; };
|
||||||
|
this.loadTableData = loadTableData || function () { return Promise.resolve(); };
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 获取图表数据
|
||||||
|
* @param {Boolean} reload 是否重新获取数据
|
||||||
|
*/
|
||||||
|
loadChartDataImpl (reload = false) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (typeof this.loadTableData !== 'function') {
|
||||||
|
reject();
|
||||||
|
} else {
|
||||||
|
if (!reload) {
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
this.loading = true;
|
||||||
|
this.loadTableData().then(tableData => {
|
||||||
|
this.chartData = {
|
||||||
|
columns: this.columns,
|
||||||
|
rows: tableData.dataList
|
||||||
|
}
|
||||||
|
this.loading = false;
|
||||||
|
if (this.chartObject) this.chartObject.resize();
|
||||||
|
resolve();
|
||||||
|
}).catch(e => {
|
||||||
|
console.error(e);
|
||||||
|
this.loading = false;
|
||||||
|
reject(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 刷新图表数据
|
||||||
|
* @param {Boolean} research 是否按照新的查询条件重新查询(调用verify函数)
|
||||||
|
*/
|
||||||
|
refreshChart (research = false) {
|
||||||
|
if (research) {
|
||||||
|
if (typeof this.searchVerify === 'function' && !this.searchVerify()) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loadChartDataImpl(true).catch(e => {});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,184 @@
|
|||||||
|
<template>
|
||||||
|
<div style="position: relative;">
|
||||||
|
<el-form label-width="100px" size="mini" label-position="right" @submit.native.prevent>
|
||||||
|
<filter-box :item-width="350">
|
||||||
|
<el-form-item label="应用名称">
|
||||||
|
<el-input class="filter-item" v-model="formAuthClient.formFilter.clientDesc"
|
||||||
|
:clearable="true" placeholder="应用名称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-button slot="operator" type="primary" :plain="true" size="mini" @click="refreshFormAuthClient(true)">查询</el-button>
|
||||||
|
<el-button slot="operator" type="primary" size="mini"
|
||||||
|
@click="onFormCreateAuthClientClick()">
|
||||||
|
新建
|
||||||
|
</el-button>
|
||||||
|
</filter-box>
|
||||||
|
</el-form>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-table :data="formAuthClient.AuthClientDetails.impl.dataList" size="mini" @sort-change="formAuthClient.AuthClientDetails.impl.onSortChange"
|
||||||
|
header-cell-class-name="table-header-gray">
|
||||||
|
<el-table-column label="序号" header-align="center" align="center" type="index" width="55px" :index="formAuthClient.AuthClientDetails.impl.getTableIndex" />
|
||||||
|
<el-table-column label="应用标识" prop="clientId">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="应用名称" prop="clientDesc">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="TOKEN 有效期" prop="accessTokenValidity">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="回调地址" prop="webServerRedirectUri">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" fixed="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button @click="onFormEditAuthClientClick(scope.row)" type="text" size="mini">
|
||||||
|
编辑
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="onDeleteClick(scope.row)" type="text" size="mini">
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<el-row type="flex" justify="end" style="margin-top: 10px;">
|
||||||
|
<el-pagination
|
||||||
|
:total="formAuthClient.AuthClientDetails.impl.totalCount"
|
||||||
|
:current-page="formAuthClient.AuthClientDetails.impl.currentPage"
|
||||||
|
:page-size="formAuthClient.AuthClientDetails.impl.pageSize"
|
||||||
|
:page-sizes="[10, 20, 50, 100]"
|
||||||
|
layout="total, prev, pager, next, sizes"
|
||||||
|
@current-change="formAuthClient.AuthClientDetails.impl.onCurrentPageChange"
|
||||||
|
@size-change="formAuthClient.AuthClientDetails.impl.onPageSizeChange">
|
||||||
|
</el-pagination>
|
||||||
|
</el-row>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
import { DropdownWidget, TableWidget, UploadWidget, ChartWidget } from '@/utils/widget.js';
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
import { uploadMixin, statsDateRangeMixin, cachePageMixin } from '@/core/mixins';
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
import { AuthClientDetailsController, DictionaryController } from '@/api';
|
||||||
|
import formCreateAuthClient from '@/views/generated/formCreateAuthClient';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'formAuthClient',
|
||||||
|
props: {
|
||||||
|
},
|
||||||
|
mixins: [uploadMixin, statsDateRangeMixin, cachePageMixin],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
formAuthClient: {
|
||||||
|
formFilter: {
|
||||||
|
clientDesc: undefined
|
||||||
|
},
|
||||||
|
formFilterCopy: {
|
||||||
|
clientDesc: undefined
|
||||||
|
},
|
||||||
|
AuthClientDetails: {
|
||||||
|
impl: new TableWidget(this.loadAuthClientDetailsData, this.loadAuthClientDetailsVerify, true)
|
||||||
|
},
|
||||||
|
isInit: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 应用客户端数据获取函数,返回Primise
|
||||||
|
*/
|
||||||
|
loadAuthClientDetailsData (params) {
|
||||||
|
if (params == null) params = {};
|
||||||
|
params = {
|
||||||
|
...params,
|
||||||
|
authClientDetailsFilter: {
|
||||||
|
clientDesc: this.formAuthClient.formFilterCopy.clientDesc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
AuthClientDetailsController.list(this, params).then(res => {
|
||||||
|
resolve({
|
||||||
|
dataList: res.data.dataList,
|
||||||
|
totalCount: res.data.totalCount
|
||||||
|
});
|
||||||
|
}).catch(e => {
|
||||||
|
reject(e);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 应用客户端数据获取检测函数,返回true正常获取数据,返回false停止获取数据
|
||||||
|
*/
|
||||||
|
loadAuthClientDetailsVerify () {
|
||||||
|
this.formAuthClient.formFilterCopy.clientDesc = this.formAuthClient.formFilter.clientDesc;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 更新应用客户端管理
|
||||||
|
*/
|
||||||
|
refreshFormAuthClient (reloadData = false) {
|
||||||
|
if (reloadData) {
|
||||||
|
this.formAuthClient.AuthClientDetails.impl.refreshTable(true, 1);
|
||||||
|
} else {
|
||||||
|
this.formAuthClient.AuthClientDetails.impl.refreshTable();
|
||||||
|
}
|
||||||
|
if (!this.formAuthClient.isInit) {
|
||||||
|
// 初始化下拉数据
|
||||||
|
}
|
||||||
|
this.formAuthClient.isInit = true;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 新建
|
||||||
|
*/
|
||||||
|
onFormCreateAuthClientClick () {
|
||||||
|
let params = {};
|
||||||
|
|
||||||
|
this.$dialog.show('新建', formCreateAuthClient, {
|
||||||
|
area: ['800px']
|
||||||
|
}, params).then(res => {
|
||||||
|
this.refreshFormAuthClient();
|
||||||
|
}).catch(e => {});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 编辑
|
||||||
|
*/
|
||||||
|
onFormEditAuthClientClick (row) {
|
||||||
|
let params = {
|
||||||
|
clientId: row.clientId
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$dialog.show('编辑', formCreateAuthClient, {
|
||||||
|
area: ['800px']
|
||||||
|
}, params).then(res => {
|
||||||
|
this.formAuthClient.AuthClientDetails.impl.refreshTable();
|
||||||
|
}).catch(e => {});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 删除
|
||||||
|
*/
|
||||||
|
onDeleteClick (row) {
|
||||||
|
let params = {
|
||||||
|
clientId: row.clientId
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$confirm('是否删除此客户端?').then(res => {
|
||||||
|
AuthClientDetailsController.delete(this, params).then(res => {
|
||||||
|
this.$message.success('删除成功');
|
||||||
|
this.formAuthClient.AuthClientDetails.impl.refreshTable();
|
||||||
|
}).catch(e => {});
|
||||||
|
}).catch(e => {});
|
||||||
|
},
|
||||||
|
onResume () {
|
||||||
|
this.refreshFormAuthClient();
|
||||||
|
},
|
||||||
|
initFormData () {
|
||||||
|
},
|
||||||
|
formInit () {
|
||||||
|
this.refreshFormAuthClient();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.formInit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,179 @@
|
|||||||
|
<template>
|
||||||
|
<div class="form-single-fragment" style="position: relative;">
|
||||||
|
<el-form ref="formCreateAuthClient" :model="formData" class="full-width-input" :rules="rules" style="width: 100%;"
|
||||||
|
label-width="150px" size="mini" label-position="right" @submit.native.prevent>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="应用标识" prop="AuthClientDetails.clientId">
|
||||||
|
<el-input class="input-item" v-model="formData.AuthClientDetails.clientId"
|
||||||
|
:disabled="isEdit" :clearable="true" placeholder="应用标识" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="应用名称" prop="AuthClientDetails.clientDesc">
|
||||||
|
<el-input class="input-item" v-model="formData.AuthClientDetails.clientDesc"
|
||||||
|
:clearable="true" placeholder="应用名称" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="客户端秘钥(明文)" prop="AuthClientDetails.clientSecretPlain">
|
||||||
|
<el-input class="input-item" v-model="formData.AuthClientDetails.clientSecretPlain"
|
||||||
|
:disabled="isEdit" :clearable="true" placeholder="客户端秘钥(明文)" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="回调地址" prop="AuthClientDetails.webServerRedirectUri">
|
||||||
|
<el-input class="input-item" v-model="formData.AuthClientDetails.webServerRedirectUri"
|
||||||
|
:clearable="true" placeholder="回调地址" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="TOKEN 有效期" prop="AuthClientDetails.accessTokenValidity">
|
||||||
|
<el-input-number class="input-item" v-model="formData.AuthClientDetails.accessTokenValidity"
|
||||||
|
:clearable="true" controls-position="right" placeholder="TOKEN 有效期" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-row class="no-scroll flex-box" type="flex" justify="end">
|
||||||
|
<el-button type="primary" size="mini" :plain="true"
|
||||||
|
@click="onCancel(false)">
|
||||||
|
取消
|
||||||
|
</el-button>
|
||||||
|
<el-button type="primary" size="mini" @click="onUpdateClick()">
|
||||||
|
保存
|
||||||
|
</el-button>
|
||||||
|
</el-row>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
import { uploadMixin, statsDateRangeMixin } from '@/core/mixins';
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
import { AuthClientDetailsController, DictionaryController } from '@/api';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'formCreateAuthClient',
|
||||||
|
props: {
|
||||||
|
clientId: {
|
||||||
|
default: undefined
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mixins: [uploadMixin, statsDateRangeMixin],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
formData: {
|
||||||
|
AuthClientDetails: {
|
||||||
|
clientId: undefined,
|
||||||
|
clientSecret: undefined,
|
||||||
|
clientSecretPlain: undefined,
|
||||||
|
clientDesc: undefined,
|
||||||
|
authorizedGrantTypes: undefined,
|
||||||
|
webServerRedirectUri: undefined,
|
||||||
|
accessTokenValidity: undefined,
|
||||||
|
refreshTokenValidity: undefined,
|
||||||
|
deletedFlag: undefined,
|
||||||
|
isDatasourceInit: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'AuthClientDetails.clientId': [
|
||||||
|
{required: true, message: '请输入应用标识', trigger: 'blur'}
|
||||||
|
],
|
||||||
|
'AuthClientDetails.accessTokenValidity': [
|
||||||
|
{required: true, message: '请输入TOKEN 有效期', trigger: 'blur'},
|
||||||
|
{type: 'integer', message: 'TOKEN 有效期只允许输入整数', trigger: 'blur', transform: (value) => Number(value)},
|
||||||
|
{type: 'number', min: 0, message: 'TOKEN 有效期必须大于0', trigger: 'blur', transform: (value) => Number(value)}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
formCreateAuthClient: {
|
||||||
|
formFilter: {
|
||||||
|
},
|
||||||
|
formFilterCopy: {
|
||||||
|
},
|
||||||
|
menuBlock: {
|
||||||
|
isInit: false
|
||||||
|
},
|
||||||
|
isInit: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onCancel (isSuccess) {
|
||||||
|
if (this.observer != null) {
|
||||||
|
this.observer.cancel(isSuccess);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 更新新建应用客户端
|
||||||
|
*/
|
||||||
|
refreshFormCreateAuthClient (reloadData = false) {
|
||||||
|
this.loadAuthClientDetailsData().then(res => {
|
||||||
|
if (!this.formCreateAuthClient.isInit) {
|
||||||
|
// 初始化下拉数据
|
||||||
|
}
|
||||||
|
this.formCreateAuthClient.isInit = true;
|
||||||
|
}).catch(e => {});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 保存
|
||||||
|
*/
|
||||||
|
onUpdateClick () {
|
||||||
|
this.$refs.formCreateAuthClient.validate((valid) => {
|
||||||
|
if (!valid) return;
|
||||||
|
let params = {
|
||||||
|
authClientDetails: {
|
||||||
|
clientId: this.formData.AuthClientDetails.clientId,
|
||||||
|
clientSecretPlain: this.formData.AuthClientDetails.clientSecretPlain,
|
||||||
|
clientDesc: this.formData.AuthClientDetails.clientDesc,
|
||||||
|
webServerRedirectUri: this.formData.AuthClientDetails.webServerRedirectUri,
|
||||||
|
accessTokenValidity: this.formData.AuthClientDetails.accessTokenValidity
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let httpCall = this.isEdit ? AuthClientDetailsController.update(this, params) : AuthClientDetailsController.add(this, params);
|
||||||
|
httpCall.then(res => {
|
||||||
|
this.$message.success('保存成功');
|
||||||
|
this.onCancel(true);
|
||||||
|
}).catch(e => {});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 获取应用客户端详细信息
|
||||||
|
*/
|
||||||
|
loadAuthClientDetailsData () {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!this.formData.AuthClientDetails.isDatasourceInit && this.isEdit) {
|
||||||
|
let params = {
|
||||||
|
clientId: this.clientId
|
||||||
|
};
|
||||||
|
AuthClientDetailsController.view(this, params).then(res => {
|
||||||
|
this.formData.AuthClientDetails = {...res.data, isDatasourceInit: true};
|
||||||
|
resolve();
|
||||||
|
}).catch(e => {
|
||||||
|
reject();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
initFormData () {
|
||||||
|
},
|
||||||
|
formInit () {
|
||||||
|
this.refreshFormCreateAuthClient();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
isEdit () {
|
||||||
|
return this.clientId != null && this.clientId !== '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.formInit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,240 @@
|
|||||||
|
<template>
|
||||||
|
<div class="form-single-fragment" style="position: relative;">
|
||||||
|
<el-form ref="formCreateUaaOperator" :model="formData" class="full-width-input" :rules="rules" style="width: 100%;"
|
||||||
|
label-width="120px" size="mini" label-position="right" @submit.native.prevent>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="登录名称" prop="SysUaaOperator.loginName">
|
||||||
|
<el-input class="input-item" v-model="formData.SysUaaOperator.loginName"
|
||||||
|
:clearable="true" placeholder="登录名称" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="操作员昵称" prop="SysUaaOperator.showName">
|
||||||
|
<el-input class="input-item" v-model="formData.SysUaaOperator.showName"
|
||||||
|
:clearable="true" placeholder="操作员昵称" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24" v-if="!isEdit">
|
||||||
|
<el-form-item label="操作员密码" prop="SysUaaOperator.password">
|
||||||
|
<el-input class="input-item" v-model="formData.SysUaaOperator.password"
|
||||||
|
:clearable="true" placeholder="密码" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24" v-if="!isEdit">
|
||||||
|
<el-form-item label="再次输入密码" prop="SysUaaOperator.repeatPassword">
|
||||||
|
<el-input class="input-item" v-model="formData.SysUaaOperator.repeatPassword"
|
||||||
|
:clearable="true" placeholder="再次输入密码" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="操作员头像" prop="SysUaaOperator.headImageUrl">
|
||||||
|
<el-upload class="upload-image-item" name="uploadFile" :headers="getUploadHeaders"
|
||||||
|
:action="getUploadActionUrl('/admin/uaaadmin/sysUaaOperator/upload')"
|
||||||
|
:data="{fieldName: 'headImageUrl', asImage: true}"
|
||||||
|
:on-success="onHeadImageUrlUploadSuccess"
|
||||||
|
:on-remove="onHeadImageUrlRemoveFile"
|
||||||
|
:before-upload="pictureFile"
|
||||||
|
:on-error="onUploadError"
|
||||||
|
:show-file-list="false">
|
||||||
|
<div v-if="formCreateUaaOperator.headImageUrl.impl.fileList[0] != null" style="position: relative">
|
||||||
|
<img class="upload-image-show"
|
||||||
|
:src="formCreateUaaOperator.headImageUrl.impl.fileList[0].url" />
|
||||||
|
<div class="upload-img-del el-icon-close"
|
||||||
|
@click.stop="() => {formCreateUaaOperator.headImageUrl.impl.fileList = []}" />
|
||||||
|
</div>
|
||||||
|
<i v-else class="el-icon-plus upload-image-item"></i>
|
||||||
|
</el-upload>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-row class="no-scroll flex-box" type="flex" justify="end">
|
||||||
|
<el-button type="primary" size="mini" :plain="true"
|
||||||
|
@click="onCancel(false)">
|
||||||
|
取消
|
||||||
|
</el-button>
|
||||||
|
<el-button type="primary" size="mini" @click="onUpdateClick()">
|
||||||
|
保存
|
||||||
|
</el-button>
|
||||||
|
</el-row>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
import { DropdownWidget, TableWidget, UploadWidget, ChartWidget } from '@/utils/widget.js';
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
import { uploadMixin, statsDateRangeMixin } from '@/core/mixins';
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
import { SysUaaOperatorController, DictionaryController } from '@/api';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'formCreateUaaOperator',
|
||||||
|
props: {
|
||||||
|
operatorId: {
|
||||||
|
default: undefined
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mixins: [uploadMixin, statsDateRangeMixin],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
formData: {
|
||||||
|
SysUaaOperator: {
|
||||||
|
operatorId: undefined,
|
||||||
|
loginName: undefined,
|
||||||
|
password: undefined,
|
||||||
|
repeatPassword: undefined,
|
||||||
|
showName: undefined,
|
||||||
|
operatorType: this.UserType.NORMAL,
|
||||||
|
headImageUrl: undefined,
|
||||||
|
deletedFlag: undefined,
|
||||||
|
isDatasourceInit: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'SysUaaOperator.loginName': [
|
||||||
|
{required: true, message: '请输入登录名称', trigger: 'blur'}
|
||||||
|
],
|
||||||
|
'SysUaaOperator.showName': [
|
||||||
|
{required: true, message: '请输入用户昵称', trigger: 'blur'}
|
||||||
|
],
|
||||||
|
'SysUaaOperator.password': [
|
||||||
|
{required: true, message: '请输入用户密码', trigger: 'blur'}
|
||||||
|
],
|
||||||
|
'SysUaaOperator.repeatPassword': [
|
||||||
|
{required: true, message: '请输入再次输入密码', trigger: 'blur'}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
formCreateUaaOperator: {
|
||||||
|
formFilter: {
|
||||||
|
},
|
||||||
|
formFilterCopy: {
|
||||||
|
},
|
||||||
|
headImageUrl: {
|
||||||
|
impl: new UploadWidget(1)
|
||||||
|
},
|
||||||
|
menuBlock: {
|
||||||
|
isInit: false
|
||||||
|
},
|
||||||
|
isInit: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onCancel (isSuccess) {
|
||||||
|
if (this.observer != null) {
|
||||||
|
this.observer.cancel(isSuccess);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 更新新建操作员
|
||||||
|
*/
|
||||||
|
refreshFormCreateUaaOperator (reloadData = false) {
|
||||||
|
this.loadSysUaaOperatorData().then(res => {
|
||||||
|
if (!this.formCreateUaaOperator.isInit) {
|
||||||
|
// 初始化下拉数据
|
||||||
|
}
|
||||||
|
this.formCreateUaaOperator.isInit = true;
|
||||||
|
}).catch(e => {});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 保存
|
||||||
|
*/
|
||||||
|
onUpdateClick () {
|
||||||
|
this.$refs.formCreateUaaOperator.validate((valid) => {
|
||||||
|
if (!valid) return;
|
||||||
|
if (!this.isEdit && this.formData.SysUaaOperator.password !== this.formData.SysUaaOperator.repeatPassword) {
|
||||||
|
this.$message.error('两次密码输入不一致,请核对!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let params = {
|
||||||
|
sysUaaOperator: {
|
||||||
|
operatorId: this.operatorId,
|
||||||
|
loginName: this.formData.SysUaaOperator.loginName,
|
||||||
|
password: this.isEdit ? undefined : this.formData.SysUaaOperator.password,
|
||||||
|
showName: this.formData.SysUaaOperator.showName,
|
||||||
|
operatorType: this.formData.SysUaaOperator.operatorType,
|
||||||
|
headImageUrl: this.formData.SysUaaOperator.headImageUrl
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let httpCall = this.isEdit ? SysUaaOperatorController.update(this, params) : SysUaaOperatorController.add(this, params)
|
||||||
|
httpCall.then(res => {
|
||||||
|
this.$message.success('保存成功');
|
||||||
|
this.onCancel(true);
|
||||||
|
}).catch(e => {});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 获取操作员详细信息
|
||||||
|
*/
|
||||||
|
loadSysUaaOperatorData () {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!this.formData.SysUaaOperator.isDatasourceInit && this.isEdit) {
|
||||||
|
let params = {
|
||||||
|
operatorId: this.operatorId
|
||||||
|
};
|
||||||
|
SysUaaOperatorController.view(this, params).then(res => {
|
||||||
|
this.formData.SysUaaOperator = {...res.data, repeatPassword: res.password, isDatasourceInit: true};
|
||||||
|
|
||||||
|
let headImageUrlDownloadParams = {
|
||||||
|
operatorId: this.formData.SysUaaOperator.operatorId,
|
||||||
|
fieldName: 'headImageUrl',
|
||||||
|
asImage: true
|
||||||
|
}
|
||||||
|
this.formCreateUaaOperator.headImageUrl.impl.fileList = this.parseUploadData(this.formData.SysUaaOperator.headImageUrl, headImageUrlDownloadParams);
|
||||||
|
resolve();
|
||||||
|
}).catch(e => {
|
||||||
|
reject();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
initFormData () {
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 用户头像上传成功
|
||||||
|
*/
|
||||||
|
onHeadImageUrlUploadSuccess (response, file, fileList) {
|
||||||
|
if (response.success) {
|
||||||
|
file.downloadUri = response.data.downloadUri;
|
||||||
|
file.filename = response.data.filename;
|
||||||
|
file.url = URL.createObjectURL(file.raw);
|
||||||
|
this.formCreateUaaOperator.headImageUrl.impl.onFileChange(file, fileList);
|
||||||
|
this.formData.SysUaaOperator.headImageUrl = this.fileListToJson(this.formCreateUaaOperator.headImageUrl.impl.fileList);
|
||||||
|
} else {
|
||||||
|
this.$message.error(response.message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 移除用户头像
|
||||||
|
*/
|
||||||
|
onHeadImageUrlRemoveFile (file, fileList) {
|
||||||
|
this.formCreateUaaOperator.headImageUrl.impl.onFileChange(file, fileList);
|
||||||
|
this.formData.SysUaaOperator.headImageUrl = this.fileListToJson(this.formCreateUaaOperator.headImageUrl.impl.fileList);
|
||||||
|
},
|
||||||
|
onUploadError (e, file, fileList) {
|
||||||
|
this.$message.error('头像上传失败');
|
||||||
|
},
|
||||||
|
onUploadLimit (files, fileList) {
|
||||||
|
this.$message.error('已经超出最大上传个数限制');
|
||||||
|
},
|
||||||
|
formInit () {
|
||||||
|
this.refreshFormCreateUaaOperator();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
isEdit () {
|
||||||
|
return this.operatorId != null && this.operatorId !== '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.formInit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,217 @@
|
|||||||
|
<template>
|
||||||
|
<div class="form-single-fragment" style="position: relative;">
|
||||||
|
<el-form ref="formCreateUaaUser" :model="formData" class="full-width-input" :rules="rules" style="width: 100%;"
|
||||||
|
label-width="120px" size="mini" label-position="right" @submit.native.prevent>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="登录名称" prop="SysUaaUser.username">
|
||||||
|
<el-input class="input-item" v-model="formData.SysUaaUser.username"
|
||||||
|
:clearable="true" placeholder="登录名称" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="用户昵称" prop="SysUaaUser.showName">
|
||||||
|
<el-input class="input-item" v-model="formData.SysUaaUser.showName"
|
||||||
|
:clearable="true" placeholder="用户昵称" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24" v-if="!isEdit">
|
||||||
|
<el-form-item label="用户密码" prop="SysUaaUser.password">
|
||||||
|
<el-input class="input-item" v-model="formData.SysUaaUser.password"
|
||||||
|
:clearable="true" placeholder="密码" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24" v-if="!isEdit">
|
||||||
|
<el-form-item label="再次输入密码" prop="SysUaaUser.repeatPassword">
|
||||||
|
<el-input class="input-item" v-model="formData.SysUaaUser.repeatPassword"
|
||||||
|
:clearable="true" placeholder="密码" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24" v-if="isEdit">
|
||||||
|
<el-form-item label="用户状态" prop="SysUaaUser.locked">
|
||||||
|
<el-select class="input-item" v-model="formData.SysUaaUser.locked" :clearable="true" filterable
|
||||||
|
placeholder="用户状态" :loading="formCreateUaaUser.locked.impl.loading"
|
||||||
|
@visible-change="formCreateUaaUser.locked.impl.onVisibleChange"
|
||||||
|
@change="onLockedValueChange">
|
||||||
|
<el-option v-for="item in formCreateUaaUser.locked.impl.dropdownList" :key="item.id" :value="item.id" :label="item.name" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-row class="no-scroll flex-box" type="flex" justify="end">
|
||||||
|
<el-button type="primary" size="mini" :plain="true"
|
||||||
|
@click="onCancel(false)">
|
||||||
|
取消
|
||||||
|
</el-button>
|
||||||
|
<el-button type="primary" size="mini" @click="onUpdateClick()">
|
||||||
|
保存
|
||||||
|
</el-button>
|
||||||
|
</el-row>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
import { DropdownWidget, TableWidget, UploadWidget, ChartWidget } from '@/utils/widget.js';
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
import { uploadMixin, statsDateRangeMixin } from '@/core/mixins';
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
import { SysUaaUserController, DictionaryController } from '@/api';
|
||||||
|
import { encrypt } from '@/utils';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'formCreateUaaUser',
|
||||||
|
props: {
|
||||||
|
userId: {
|
||||||
|
default: undefined
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mixins: [uploadMixin, statsDateRangeMixin],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
formData: {
|
||||||
|
SysUaaUser: {
|
||||||
|
userId: undefined,
|
||||||
|
username: undefined,
|
||||||
|
password: undefined,
|
||||||
|
repeatPassword: undefined,
|
||||||
|
showName: undefined,
|
||||||
|
locked: this.UserStatus.USED,
|
||||||
|
isDatasourceInit: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'SysUaaUser.username': [
|
||||||
|
{required: true, message: '请输入登录名称', trigger: 'blur'}
|
||||||
|
],
|
||||||
|
'SysUaaUser.password': [
|
||||||
|
{required: true, message: '请输入密码', trigger: 'blur'}
|
||||||
|
],
|
||||||
|
'SysUaaUser.repeatPassword': [
|
||||||
|
{required: true, message: '请输入再次输入密码', trigger: 'blur'}
|
||||||
|
],
|
||||||
|
'SysUaaUser.showName': [
|
||||||
|
{required: true, message: '请输入用户昵称', trigger: 'blur'}
|
||||||
|
],
|
||||||
|
'SysUaaUser.locked': [
|
||||||
|
{required: true, message: '请输入用户状态', trigger: 'blur'}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
formCreateUaaUser: {
|
||||||
|
formFilter: {
|
||||||
|
},
|
||||||
|
formFilterCopy: {
|
||||||
|
},
|
||||||
|
locked: {
|
||||||
|
impl: new DropdownWidget(this.loadLockedDropdownList)
|
||||||
|
},
|
||||||
|
menuBlock: {
|
||||||
|
isInit: false
|
||||||
|
},
|
||||||
|
isInit: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onCancel (isSuccess) {
|
||||||
|
if (this.observer != null) {
|
||||||
|
this.observer.cancel(isSuccess);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 用户状态下拉数据获取函数
|
||||||
|
*/
|
||||||
|
loadLockedDropdownList () {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let params = {};
|
||||||
|
DictionaryController.dictUserStatus(this, params).then(res => {
|
||||||
|
resolve(res.getList());
|
||||||
|
}).catch(e => {
|
||||||
|
reject(e);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 用户状态选中值改变
|
||||||
|
*/
|
||||||
|
onLockedValueChange (value) {
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 更新新建UAA用户
|
||||||
|
*/
|
||||||
|
refreshFormCreateUaaUser (reloadData = false) {
|
||||||
|
this.loadSysUaaUserData().then(res => {
|
||||||
|
if (!this.formCreateUaaUser.isInit) {
|
||||||
|
// 初始化下拉数据
|
||||||
|
}
|
||||||
|
this.formCreateUaaUser.isInit = true;
|
||||||
|
}).catch(e => {});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 保存
|
||||||
|
*/
|
||||||
|
onUpdateClick () {
|
||||||
|
this.$refs.formCreateUaaUser.validate((valid) => {
|
||||||
|
if (!valid) return;
|
||||||
|
if (!this.isEdit && this.formData.SysUaaUser.password !== this.formData.SysUaaUser.repeatPassword) {
|
||||||
|
this.$message.error('两次密码输入不一致,请核对!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let params = {
|
||||||
|
sysUaaUser: {
|
||||||
|
userId: this.userId,
|
||||||
|
username: this.formData.SysUaaUser.username,
|
||||||
|
password: this.isEdit ? undefined : encrypt(this.formData.SysUaaUser.password),
|
||||||
|
showName: this.formData.SysUaaUser.showName,
|
||||||
|
locked: this.formData.SysUaaUser.locked
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let httpCall = this.isEdit ? SysUaaUserController.update(this, params) : SysUaaUserController.add(this, params);
|
||||||
|
httpCall.then(res => {
|
||||||
|
this.$message.success('保存成功');
|
||||||
|
this.onCancel(true);
|
||||||
|
}).catch(e => {});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 获取UAA用户详细信息
|
||||||
|
*/
|
||||||
|
loadSysUaaUserData () {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!this.formData.SysUaaUser.isDatasourceInit && this.isEdit) {
|
||||||
|
let params = {
|
||||||
|
userId: this.userId
|
||||||
|
};
|
||||||
|
SysUaaUserController.view(this, params).then(res => {
|
||||||
|
this.formData.SysUaaUser = {...res.data, repeatPassword: res.password, isDatasourceInit: true};
|
||||||
|
if (this.formData.SysUaaUser.lockedDictMap) this.formCreateUaaUser.locked.impl.dropdownList = [this.formData.SysUaaUser.lockedDictMap];
|
||||||
|
resolve();
|
||||||
|
}).catch(e => {
|
||||||
|
reject();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
initFormData () {
|
||||||
|
this.formCreateUaaUser.locked.impl.onVisibleChange(true);
|
||||||
|
},
|
||||||
|
formInit () {
|
||||||
|
this.refreshFormCreateUaaUser();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
isEdit () {
|
||||||
|
return this.userId != null && this.userId !== '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.formInit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,242 @@
|
|||||||
|
<template>
|
||||||
|
<div style="position: relative;">
|
||||||
|
<el-form label-width="100px" size="mini" label-position="right" @submit.native.prevent>
|
||||||
|
<filter-box :item-width="350">
|
||||||
|
<el-form-item label="操作员类型">
|
||||||
|
<el-select class="filter-item" v-model="formUaaOperator.formFilter.userType" :clearable="true" filterable
|
||||||
|
placeholder="操作员类型" :loading="formUaaOperator.userType.impl.loading"
|
||||||
|
@visible-change="formUaaOperator.userType.impl.onVisibleChange"
|
||||||
|
@change="onUserTypeValueChange">
|
||||||
|
<el-option v-for="item in formUaaOperator.userType.impl.dropdownList" :key="item.id" :value="item.id" :label="item.name" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="操作员名称">
|
||||||
|
<el-input class="filter-item" v-model="formUaaOperator.formFilter.searchString"
|
||||||
|
:clearable="true" placeholder="操作员登录名称 / 昵称模糊查询" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-button slot="operator" type="primary" :plain="true" size="mini" @click="refreshFormUaaOperator(true)">查询</el-button>
|
||||||
|
<el-button slot="operator" type="primary" size="mini" @click="onFormCreateUaaOperatorClick()">
|
||||||
|
新建
|
||||||
|
</el-button>
|
||||||
|
</filter-box>
|
||||||
|
</el-form>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-table :data="formUaaOperator.SysUaaOperator.impl.dataList" size="mini" @sort-change="formUaaOperator.SysUaaOperator.impl.onSortChange"
|
||||||
|
header-cell-class-name="table-header-gray">
|
||||||
|
<el-table-column label="序号" header-align="center" align="center" type="index" width="55px" :index="formUaaOperator.SysUaaOperator.impl.getTableIndex" />
|
||||||
|
<el-table-column label="登录名称" prop="loginName">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="昵称" prop="showName">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作员类型" prop="operatorTypeDictMap.name">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作员头像" min-width="100px">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-image v-for="item in parseUploadData(scope.row.headImageUrl, {operatorId: scope.row.operatorId, fieldName: 'headImageUrl', asImage: true})"
|
||||||
|
:preview-src-list="getPictureList(scope.row.headImageUrl, {operatorId: scope.row.operatorId, fieldName: 'headImageUrl', asImage: true})"
|
||||||
|
class="table-cell-image" :key="item.url" :src="item.url" fit="fill">
|
||||||
|
<div slot="error" class="table-cell-image">
|
||||||
|
<i class="el-icon-picture-outline"></i>
|
||||||
|
</div>
|
||||||
|
</el-image>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" fixed="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button @click="onFormEditUaaOperatorClick(scope.row)" type="text" size="mini">
|
||||||
|
编辑
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="onResetPasswordClick(scope.row)" type="text" size="mini">
|
||||||
|
重置密码
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="onDeleteClick(scope.row)" type="text" size="mini">
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<el-row type="flex" justify="end" style="margin-top: 10px;">
|
||||||
|
<el-pagination
|
||||||
|
:total="formUaaOperator.SysUaaOperator.impl.totalCount"
|
||||||
|
:current-page="formUaaOperator.SysUaaOperator.impl.currentPage"
|
||||||
|
:page-size="formUaaOperator.SysUaaOperator.impl.pageSize"
|
||||||
|
:page-sizes="[10, 20, 50, 100]"
|
||||||
|
layout="total, prev, pager, next, sizes"
|
||||||
|
@current-change="formUaaOperator.SysUaaOperator.impl.onCurrentPageChange"
|
||||||
|
@size-change="formUaaOperator.SysUaaOperator.impl.onPageSizeChange">
|
||||||
|
</el-pagination>
|
||||||
|
</el-row>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
import { DropdownWidget, TableWidget, UploadWidget, ChartWidget } from '@/utils/widget.js';
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
import { uploadMixin, statsDateRangeMixin, cachePageMixin } from '@/core/mixins';
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
import { SysUaaOperatorController, DictionaryController } from '@/api';
|
||||||
|
import formCreateUaaOperator from '@/views/generated/formCreateUaaOperator';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'formUaaOperator',
|
||||||
|
props: {
|
||||||
|
},
|
||||||
|
mixins: [uploadMixin, statsDateRangeMixin, cachePageMixin],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
formUaaOperator: {
|
||||||
|
formFilter: {
|
||||||
|
userType: undefined,
|
||||||
|
searchString: undefined
|
||||||
|
},
|
||||||
|
formFilterCopy: {
|
||||||
|
userType: undefined,
|
||||||
|
searchString: undefined
|
||||||
|
},
|
||||||
|
userType: {
|
||||||
|
impl: new DropdownWidget(this.loadUserTypeDropdownList)
|
||||||
|
},
|
||||||
|
SysUaaOperator: {
|
||||||
|
impl: new TableWidget(this.loadSysUaaOperatorData, this.loadSysUaaOperatorVerify, true)
|
||||||
|
},
|
||||||
|
isInit: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 操作员数据获取函数,返回Primise
|
||||||
|
*/
|
||||||
|
loadSysUaaOperatorData (params) {
|
||||||
|
if (params == null) params = {};
|
||||||
|
params = {
|
||||||
|
...params,
|
||||||
|
sysUaaOperatorFilter: {
|
||||||
|
operatorType: this.formUaaOperator.formFilterCopy.userType,
|
||||||
|
searchString: this.formUaaOperator.formFilterCopy.searchString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
SysUaaOperatorController.list(this, params).then(res => {
|
||||||
|
resolve({
|
||||||
|
dataList: res.data.dataList,
|
||||||
|
totalCount: res.data.totalCount
|
||||||
|
});
|
||||||
|
}).catch(e => {
|
||||||
|
reject(e);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 操作员数据获取检测函数,返回true正常获取数据,返回false停止获取数据
|
||||||
|
*/
|
||||||
|
loadSysUaaOperatorVerify () {
|
||||||
|
this.formUaaOperator.formFilterCopy.userType = this.formUaaOperator.formFilter.userType;
|
||||||
|
this.formUaaOperator.formFilterCopy.searchString = this.formUaaOperator.formFilter.searchString;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 用户类型下拉数据获取函数
|
||||||
|
*/
|
||||||
|
loadUserTypeDropdownList () {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let params = {};
|
||||||
|
DictionaryController.dictUserType(this, params).then(res => {
|
||||||
|
resolve(res.getList());
|
||||||
|
}).catch(e => {
|
||||||
|
reject(e);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 用户类型选中值改变
|
||||||
|
*/
|
||||||
|
onUserTypeValueChange (value) {
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 更新操作员管理
|
||||||
|
*/
|
||||||
|
refreshFormUaaOperator (reloadData = false) {
|
||||||
|
if (reloadData) {
|
||||||
|
this.formUaaOperator.SysUaaOperator.impl.refreshTable(true, 1);
|
||||||
|
} else {
|
||||||
|
this.formUaaOperator.SysUaaOperator.impl.refreshTable();
|
||||||
|
}
|
||||||
|
if (!this.formUaaOperator.isInit) {
|
||||||
|
// 初始化下拉数据
|
||||||
|
}
|
||||||
|
this.formUaaOperator.isInit = true;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 新建
|
||||||
|
*/
|
||||||
|
onFormCreateUaaOperatorClick () {
|
||||||
|
let params = {};
|
||||||
|
|
||||||
|
this.$dialog.show('新建', formCreateUaaOperator, {
|
||||||
|
area: ['500px']
|
||||||
|
}, params).then(res => {
|
||||||
|
this.refreshFormUaaOperator();
|
||||||
|
}).catch(e => {});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 编辑
|
||||||
|
*/
|
||||||
|
onFormEditUaaOperatorClick (row) {
|
||||||
|
let params = {
|
||||||
|
operatorId: row.operatorId
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$dialog.show('编辑', formCreateUaaOperator, {
|
||||||
|
area: ['500px']
|
||||||
|
}, params).then(res => {
|
||||||
|
this.formUaaOperator.SysUaaOperator.impl.refreshTable();
|
||||||
|
}).catch(e => {});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 删除
|
||||||
|
*/
|
||||||
|
onDeleteClick (row) {
|
||||||
|
let params = {
|
||||||
|
operatorId: row.operatorId
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$confirm('是否删除此操作员?').then(res => {
|
||||||
|
SysUaaOperatorController.delete(this, params).then(res => {
|
||||||
|
this.$message.success('删除成功');
|
||||||
|
this.formUaaOperator.SysUaaOperator.impl.refreshTable();
|
||||||
|
}).catch(e => {});
|
||||||
|
}).catch(e => {});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 重置密码
|
||||||
|
*/
|
||||||
|
onResetPasswordClick (row) {
|
||||||
|
this.$confirm('是否重置操作员密码?').then(res => {
|
||||||
|
let params = {
|
||||||
|
operatorId: row.operatorId
|
||||||
|
};
|
||||||
|
|
||||||
|
SysUaaOperatorController.resetPassword(this, params).then(res => {
|
||||||
|
this.$message.success('重置密码成功');
|
||||||
|
}).catch(e => {});
|
||||||
|
}).catch(e => {});
|
||||||
|
},
|
||||||
|
onResume () {
|
||||||
|
this.refreshFormUaaOperator();
|
||||||
|
},
|
||||||
|
initFormData () {
|
||||||
|
},
|
||||||
|
formInit () {
|
||||||
|
this.refreshFormUaaOperator();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.formInit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,231 @@
|
|||||||
|
<template>
|
||||||
|
<div style="position: relative;">
|
||||||
|
<el-form label-width="100px" size="mini" label-position="right" @submit.native.prevent>
|
||||||
|
<filter-box :item-width="350">
|
||||||
|
<el-form-item label="用户状态">
|
||||||
|
<el-select class="filter-item" v-model="formUaaUser.formFilter.userStatus" :clearable="true" filterable
|
||||||
|
placeholder="用户状态" :loading="formUaaUser.userStatus.impl.loading"
|
||||||
|
@visible-change="formUaaUser.userStatus.impl.onVisibleChange"
|
||||||
|
@change="onUserStatusValueChange">
|
||||||
|
<el-option v-for="item in formUaaUser.userStatus.impl.dropdownList" :key="item.id" :value="item.id" :label="item.name" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="用户名称">
|
||||||
|
<el-input class="filter-item" v-model="formUaaUser.formFilter.searchString"
|
||||||
|
:clearable="true" placeholder="用户登录名称 / 用户昵称模糊查询" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-button slot="operator" type="primary" :plain="true" size="mini" @click="refreshFormUaaUser(true)">查询</el-button>
|
||||||
|
<el-button slot="operator" type="primary" size="mini" @click="onFormCreateUaaUserClick()">
|
||||||
|
新建
|
||||||
|
</el-button>
|
||||||
|
</filter-box>
|
||||||
|
</el-form>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-table :data="formUaaUser.SysUaaUser.impl.dataList" size="mini" @sort-change="formUaaUser.SysUaaUser.impl.onSortChange"
|
||||||
|
header-cell-class-name="table-header-gray">
|
||||||
|
<el-table-column label="序号" header-align="center" align="center" type="index" width="55px" :index="formUaaUser.SysUaaUser.impl.getTableIndex" />
|
||||||
|
<el-table-column label="登录名称" prop="username">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="用户昵称" prop="showName">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="用户状态" prop="lockedDictMap.name">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" fixed="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button @click="onFormEditUaaUserClick(scope.row)" type="text" size="mini">
|
||||||
|
编辑
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="onResetPasswordClick(scope.row)" type="text" size="mini">
|
||||||
|
重置密码
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="onDeleteClick(scope.row)" type="text" size="mini">
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<el-row type="flex" justify="end" style="margin-top: 10px;">
|
||||||
|
<el-pagination
|
||||||
|
:total="formUaaUser.SysUaaUser.impl.totalCount"
|
||||||
|
:current-page="formUaaUser.SysUaaUser.impl.currentPage"
|
||||||
|
:page-size="formUaaUser.SysUaaUser.impl.pageSize"
|
||||||
|
:page-sizes="[10, 20, 50, 100]"
|
||||||
|
layout="total, prev, pager, next, sizes"
|
||||||
|
@current-change="formUaaUser.SysUaaUser.impl.onCurrentPageChange"
|
||||||
|
@size-change="formUaaUser.SysUaaUser.impl.onPageSizeChange">
|
||||||
|
</el-pagination>
|
||||||
|
</el-row>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
import { DropdownWidget, TableWidget, UploadWidget, ChartWidget } from '@/utils/widget.js';
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
import { uploadMixin, statsDateRangeMixin, cachePageMixin } from '@/core/mixins';
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
import { SysUaaUserController, DictionaryController } from '@/api';
|
||||||
|
import formCreateUaaUser from '@/views/generated/formCreateUaaUser';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'formUaaUser',
|
||||||
|
props: {
|
||||||
|
},
|
||||||
|
mixins: [uploadMixin, statsDateRangeMixin, cachePageMixin],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
formUaaUser: {
|
||||||
|
formFilter: {
|
||||||
|
userStatus: undefined,
|
||||||
|
searchString: undefined
|
||||||
|
},
|
||||||
|
formFilterCopy: {
|
||||||
|
userStatus: undefined,
|
||||||
|
searchString: undefined
|
||||||
|
},
|
||||||
|
userStatus: {
|
||||||
|
impl: new DropdownWidget(this.loadUserStatusDropdownList)
|
||||||
|
},
|
||||||
|
SysUaaUser: {
|
||||||
|
impl: new TableWidget(this.loadSysUaaUserData, this.loadSysUaaUserVerify, true)
|
||||||
|
},
|
||||||
|
isInit: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* UAA用户数据获取函数,返回Primise
|
||||||
|
*/
|
||||||
|
loadSysUaaUserData (params) {
|
||||||
|
if (params == null) params = {};
|
||||||
|
params = {
|
||||||
|
...params,
|
||||||
|
sysUaaUserFilter: {
|
||||||
|
locked: this.formUaaUser.formFilterCopy.userStatus,
|
||||||
|
searchString: this.formUaaUser.formFilterCopy.searchString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
SysUaaUserController.list(this, params).then(res => {
|
||||||
|
resolve({
|
||||||
|
dataList: res.data.dataList,
|
||||||
|
totalCount: res.data.totalCount
|
||||||
|
});
|
||||||
|
}).catch(e => {
|
||||||
|
reject(e);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* UAA用户数据获取检测函数,返回true正常获取数据,返回false停止获取数据
|
||||||
|
*/
|
||||||
|
loadSysUaaUserVerify () {
|
||||||
|
this.formUaaUser.formFilterCopy.userStatus = this.formUaaUser.formFilter.userStatus;
|
||||||
|
this.formUaaUser.formFilterCopy.searchString = this.formUaaUser.formFilter.searchString;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 用户状态下拉数据获取函数
|
||||||
|
*/
|
||||||
|
loadUserStatusDropdownList () {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let params = {};
|
||||||
|
DictionaryController.dictUserStatus(this, params).then(res => {
|
||||||
|
resolve(res.getList());
|
||||||
|
}).catch(e => {
|
||||||
|
reject(e);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 用户状态选中值改变
|
||||||
|
*/
|
||||||
|
onUserStatusValueChange (value) {
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 更新UAA用户管理
|
||||||
|
*/
|
||||||
|
refreshFormUaaUser (reloadData = false) {
|
||||||
|
if (reloadData) {
|
||||||
|
this.formUaaUser.SysUaaUser.impl.refreshTable(true, 1);
|
||||||
|
} else {
|
||||||
|
this.formUaaUser.SysUaaUser.impl.refreshTable();
|
||||||
|
}
|
||||||
|
if (!this.formUaaUser.isInit) {
|
||||||
|
// 初始化下拉数据
|
||||||
|
}
|
||||||
|
this.formUaaUser.isInit = true;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 新建
|
||||||
|
*/
|
||||||
|
onFormCreateUaaUserClick () {
|
||||||
|
let params = {};
|
||||||
|
|
||||||
|
this.$dialog.show('新建', formCreateUaaUser, {
|
||||||
|
area: ['500px']
|
||||||
|
}, params).then(res => {
|
||||||
|
this.refreshFormUaaUser();
|
||||||
|
}).catch(e => {});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 编辑
|
||||||
|
*/
|
||||||
|
onFormEditUaaUserClick (row) {
|
||||||
|
let params = {
|
||||||
|
userId: row.userId
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$dialog.show('编辑', formCreateUaaUser, {
|
||||||
|
area: ['500px']
|
||||||
|
}, params).then(res => {
|
||||||
|
this.formUaaUser.SysUaaUser.impl.refreshTable();
|
||||||
|
}).catch(e => {});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 删除
|
||||||
|
*/
|
||||||
|
onDeleteClick (row) {
|
||||||
|
let params = {
|
||||||
|
userId: row.userId
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$confirm('是否删除此用户?').then(res => {
|
||||||
|
SysUaaUserController.delete(this, params).then(res => {
|
||||||
|
this.$message.success('删除成功');
|
||||||
|
this.formUaaUser.SysUaaUser.impl.refreshTable();
|
||||||
|
}).catch(e => {});
|
||||||
|
}).catch(e => {});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 重置密码
|
||||||
|
*/
|
||||||
|
onResetPasswordClick (row) {
|
||||||
|
this.$confirm('是否重置用户密码?').then(res => {
|
||||||
|
let params = {
|
||||||
|
uaaUserId: row.userId
|
||||||
|
};
|
||||||
|
|
||||||
|
SysUaaUserController.resetPassword(this, params).then(res => {
|
||||||
|
this.$message.success('重置密码成功');
|
||||||
|
}).catch(e => {});
|
||||||
|
}).catch(e => {});
|
||||||
|
},
|
||||||
|
onResume () {
|
||||||
|
this.refreshFormUaaUser();
|
||||||
|
},
|
||||||
|
initFormData () {
|
||||||
|
},
|
||||||
|
formInit () {
|
||||||
|
this.refreshFormUaaUser();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.formInit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
<template>
|
||||||
|
<el-breadcrumb class="app-breadcrumb" separator="/">
|
||||||
|
<el-breadcrumb-item :to="{name: 'welcome'}" :replace="true">
|
||||||
|
<i class="el-icon-s-home" style="margin-right: 5px;" />主页
|
||||||
|
</el-breadcrumb-item>
|
||||||
|
<el-breadcrumb-item v-for="item in menuPathList" :key="item.menuId">
|
||||||
|
{{item.menuName}}
|
||||||
|
</el-breadcrumb-item>
|
||||||
|
</el-breadcrumb>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapGetters, mapMutations } from 'vuex';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
created () {
|
||||||
|
this.getBreadcrumb();
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
menuPathList: null
|
||||||
|
};
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
$route (newValue) {
|
||||||
|
if (newValue.name === 'welcome') this.setCurrentMenuId(null);
|
||||||
|
this.getBreadcrumb();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getBreadcrumb () {
|
||||||
|
this.menuPathList = this.getCurrentMenuPath;
|
||||||
|
},
|
||||||
|
...mapMutations(['setCurrentMenuId'])
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters(['getCurrentMenuPath'])
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||||
|
.app-breadcrumb.el-breadcrumb {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 60px;
|
||||||
|
margin-left: 10px;
|
||||||
|
.no-redirect {
|
||||||
|
color: #97a8be;
|
||||||
|
cursor: text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
<template>
|
||||||
|
<div class="form-single-fragment" style="position: relative;">
|
||||||
|
<el-form ref="formModifyPassword" :model="formData" class="full-width-input" :rules="rules" style="width: 100%;"
|
||||||
|
label-width="120px" size="mini" label-position="right" @submit.native.prevent>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="旧密码" prop="oldPassword">
|
||||||
|
<el-input class="input-item" v-model.trim="formData.oldPassword"
|
||||||
|
:clearable="true" placeholder="旧密码" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="新密码" prop="password">
|
||||||
|
<el-input class="input-item" v-model.trim="formData.password"
|
||||||
|
:clearable="true" placeholder="新密码" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="再次输入新密码" prop="repeatPassword">
|
||||||
|
<el-input class="input-item" v-model.trim="formData.repeatPassword"
|
||||||
|
:clearable="true" placeholder="再次输入新密码" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-row class="no-scroll flex-box" type="flex" justify="end">
|
||||||
|
<el-button type="primary" size="mini" :plain="true"
|
||||||
|
@click="onCancel(false)">
|
||||||
|
取消
|
||||||
|
</el-button>
|
||||||
|
<el-button type="primary" size="mini" @click="onSave()">
|
||||||
|
保存
|
||||||
|
</el-button>
|
||||||
|
</el-row>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { SystemController } from '@/api';
|
||||||
|
import { encrypt } from '@/utils';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
formData: {
|
||||||
|
oldPassword: undefined,
|
||||||
|
password: undefined,
|
||||||
|
repeatPassword: undefined
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'oldPassword': [
|
||||||
|
{required: true, message: '请输入旧密码', trigger: 'blur'}
|
||||||
|
],
|
||||||
|
'password': [
|
||||||
|
{required: true, message: '请输入新密码', trigger: 'blur'}
|
||||||
|
],
|
||||||
|
'repeatPassword': [
|
||||||
|
{required: true, message: '请输入新密码', trigger: 'blur'}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onCancel (isSuccess) {
|
||||||
|
if (this.observer != null) {
|
||||||
|
this.observer.cancel(isSuccess);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSave () {
|
||||||
|
this.$refs.formModifyPassword.validate((valid) => {
|
||||||
|
if (!valid) return;
|
||||||
|
if (this.formData.password !== this.formData.repeatPassword) {
|
||||||
|
this.$message.error('两次密码输入不一致,请核对!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let params = {
|
||||||
|
oldPass: encrypt(this.formData.oldPassword),
|
||||||
|
newPass: encrypt(this.formData.password)
|
||||||
|
};
|
||||||
|
|
||||||
|
SystemController.changePassword(this, params).then(res => {
|
||||||
|
this.$message.success('密码修改成功');
|
||||||
|
this.onCancel(true);
|
||||||
|
}).catch(e => {});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
<template>
|
||||||
|
<div class="menu-wrapper">
|
||||||
|
<el-menu-item ref="item" :index="menu.menuId + ''" :key="menu.menuId" v-if="menu.children == null || menu.children.length <= 0">
|
||||||
|
<template slot="title">
|
||||||
|
<i v-if="menu.icon" :class="menu.icon" style="margin-right: 5px; font-size: 18px;" :style="getIconStyle(menu.icon)"></i>
|
||||||
|
<span slot="title" :style="getTextStyle(!menu.icon)">{{menu.menuName}}</span>
|
||||||
|
</template>
|
||||||
|
</el-menu-item>
|
||||||
|
<el-submenu v-else :index="menu.menuId + ''" :key="menu.menuId">
|
||||||
|
<template slot="title">
|
||||||
|
<i v-if="menu.icon" :class="menu.icon" style="margin-right: 5px; font-size: 18px;" :style="getIconStyle(menu.icon)"></i>
|
||||||
|
<span slot="title" :style="getTextStyle(!menu.icon)" v-show="!getCollapse">{{menu.menuName}}</span>
|
||||||
|
</template>
|
||||||
|
<template v-for="child in menu.children">
|
||||||
|
<menu-item class="nest-menu" :menu="child" :isChild="true" :key="child.menuId" />
|
||||||
|
</template>
|
||||||
|
</el-submenu>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {mapGetters} from 'vuex'
|
||||||
|
export default {
|
||||||
|
name: 'menuItem',
|
||||||
|
props: {
|
||||||
|
menu: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
isChild: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getIconStyle (isShow) {
|
||||||
|
if (isShow && this.isChild) {
|
||||||
|
return [
|
||||||
|
{ 'margin-left': '13px' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getTextStyle (isShow) {
|
||||||
|
if (isShow && this.isChild) {
|
||||||
|
return [
|
||||||
|
{ 'padding-left': '13px' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
showText () {
|
||||||
|
return !this.getCollapse;
|
||||||
|
},
|
||||||
|
...mapGetters(['getCollapse'])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
<template>
|
||||||
|
<div style="height: 100%; position: relative;" class="sidebar-bg">
|
||||||
|
<div class="sidebar-title">
|
||||||
|
<img :src="logoImage" style="margin: 20px 60px 10px 60px; width: 80px; height: 80px; border-radius: 50%;" />
|
||||||
|
<p class="sidebar-title-text">{{getProjectName()}}</p>
|
||||||
|
</div>
|
||||||
|
<div style="height: 100%; padding-bottom: 160px;">
|
||||||
|
<el-scrollbar wrap-class="scrollbar_dropdown__wrap" style="height: 100%;">
|
||||||
|
<el-menu ref="menu" mode="vertical" :default-active="getCurrentMenuId" :unique-opened="true" @select="selectMenu"
|
||||||
|
text-color="white" active-text-color="white" :collapse="getCollapse" >
|
||||||
|
<template v-for="menu in getMenuList">
|
||||||
|
<menu-item :menu="menu" :key="menu.menuId" />
|
||||||
|
</template>
|
||||||
|
</el-menu>
|
||||||
|
</el-scrollbar>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import menuItem from './menu-item.vue';
|
||||||
|
import { mapGetters, mapMutations } from 'vuex';
|
||||||
|
import projectConfig from '@/core/config';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
isCollapse: false,
|
||||||
|
collapseLeft: '200px',
|
||||||
|
showCollapseBtn: true,
|
||||||
|
logoImage: require('../../../../assets/img/logo.jpg')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
'menu-item': menuItem
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
getCollapseStyle () {
|
||||||
|
return [{
|
||||||
|
left: this.collapseLeft
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
...mapGetters(['getMenuList', 'getCollapse', 'getCurrentMenuPath', 'getCurrentMenuId'])
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onCollapseChange () {
|
||||||
|
this.showCollapseBtn = false;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.setCollapse(!this.getCollapse);
|
||||||
|
this.collapseLeft = this.getCollapse ? '65px' : '200px';
|
||||||
|
this.showCollapseBtn = true;
|
||||||
|
}, 100);
|
||||||
|
},
|
||||||
|
getProjectName () {
|
||||||
|
if (this.getCollapse) {
|
||||||
|
return projectConfig.projectName.substr(0, 1);
|
||||||
|
} else {
|
||||||
|
return projectConfig.projectName;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
selectMenu (index, path) {
|
||||||
|
if (this.getCurrentMenuId === index) return;
|
||||||
|
// 单页面清空所有tags和cachePage
|
||||||
|
this.clearAllTags();
|
||||||
|
this.setCurrentMenuId(index);
|
||||||
|
},
|
||||||
|
...mapMutations(['setCollapse', 'clearAllTags', 'setCurrentMenuId'])
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
<template>
|
||||||
|
<el-container :style="getMainStyle">
|
||||||
|
<el-aside width='200px' class="sidebar">
|
||||||
|
<side-bar style="overflow: hidden"></side-bar>
|
||||||
|
</el-aside>
|
||||||
|
<el-container style="background-color: rgb(235,235,235)">
|
||||||
|
<el-header class="header">
|
||||||
|
<breadcrumb class="breadcrumb-container" style="flex-grow: 1;" />
|
||||||
|
<div class="header-menu">
|
||||||
|
<el-dropdown class="user-dropdown" trigger="click" @command="handleCommand">
|
||||||
|
<span class="el-dropdown-link">{{getUserInfo.showName}}<i class="el-icon-arrow-down el-icon--right"></i>
|
||||||
|
</span>
|
||||||
|
<el-dropdown-menu slot="dropdown">
|
||||||
|
<el-dropdown-item class="user-dropdown-item" command="modifyPassword">修改密码</el-dropdown-item>
|
||||||
|
<el-dropdown-item class="user-dropdown-item" command="logout">退出登录</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</el-dropdown>
|
||||||
|
<img :src="getUserInfo.headerImageUrl || header" class="header-img" />
|
||||||
|
</div>
|
||||||
|
</el-header>
|
||||||
|
<el-main style="padding: 15px 0px;">
|
||||||
|
<el-scrollbar :style="getContextStyle" wrap-class="scrollbar_dropdown__wrap">
|
||||||
|
<transition name="fade" mode="out-in">
|
||||||
|
<keep-alive :include="getCachePages">
|
||||||
|
<router-view style="margin: 0px 15px; background-color: white; overflow: hidden; padding: 20px;" :style="getRouterViewStyle" />
|
||||||
|
</keep-alive>
|
||||||
|
</transition>
|
||||||
|
</el-scrollbar>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</el-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import SideBar from './components/sidebar/sidebar.vue';
|
||||||
|
import { mapGetters, mapMutations } from 'vuex';
|
||||||
|
import Breadcrumb from './components/breadcrumb';
|
||||||
|
import formModifyPassword from './components/formModifyPassword/index.vue';
|
||||||
|
import { SystemController } from '@/api';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
header: require('../../assets/img/default-header.jpg')
|
||||||
|
};
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
'side-bar': SideBar,
|
||||||
|
'breadcrumb': Breadcrumb
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toggleSideBar () {
|
||||||
|
this.setCollapse(!this.getCollapse);
|
||||||
|
},
|
||||||
|
resetDocumentClientHeight () {
|
||||||
|
let timerID;
|
||||||
|
let _this = this;
|
||||||
|
return function () {
|
||||||
|
clearTimeout(timerID);
|
||||||
|
timerID = setTimeout(() => {
|
||||||
|
var h = document.documentElement['clientHeight'];
|
||||||
|
_this.setClientHeight(h);
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleCommand (command) {
|
||||||
|
if (command === 'logout') {
|
||||||
|
this.$confirm('是否退出登录?', '', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
let options = {
|
||||||
|
headers: {
|
||||||
|
Authorization: window.sessionStorage.getItem('token')
|
||||||
|
},
|
||||||
|
showMask: false
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemController.logout(this, {}, options).catch(e => {});
|
||||||
|
this.clearAllTags();
|
||||||
|
window.sessionStorage.removeItem('token');
|
||||||
|
window.sessionStorage.removeItem('isUaaLogin');
|
||||||
|
this.$router.replace({name: 'login'});
|
||||||
|
}).catch(e => {});
|
||||||
|
} else if (command === 'modifyPassword') {
|
||||||
|
this.$dialog.show('修改密码', formModifyPassword, {
|
||||||
|
area: ['500px']
|
||||||
|
}, {}).catch(e => {});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
...mapMutations(['setClientHeight', 'clearAllTags'])
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
getMainStyle () {
|
||||||
|
return [
|
||||||
|
{'height': this.getClientHeight + 'px'}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
getContextStyle () {
|
||||||
|
return [
|
||||||
|
{'height': (this.getClientHeight - 90) + 'px'}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
getRouterViewStyle () {
|
||||||
|
return [
|
||||||
|
{'min-height': (this.getClientHeight - 90) + 'px'}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
...mapGetters(['getClientHeight', 'getInputParams', 'getUserInfo', 'getCollapse', 'getCachePages', 'getMenuItem'])
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
let resetHeight = this.resetDocumentClientHeight();
|
||||||
|
resetHeight();
|
||||||
|
|
||||||
|
window.onresize = () => {
|
||||||
|
resetHeight();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
getMenuItem: {
|
||||||
|
handler (newValue) {
|
||||||
|
if (newValue == null) {
|
||||||
|
if (this.$route.name !== 'welcome') {
|
||||||
|
this.$router.replace({
|
||||||
|
name: 'welcome'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.$router.replace({
|
||||||
|
name: newValue.formRouterName
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
<template>
|
||||||
|
<div class="login-form">
|
||||||
|
<el-card class="box-card" style="width: 30vw; background-color: rgba(255, 255, 255, 0.9); border-width: 0px;" :body-style="{ padding: '40px' }">
|
||||||
|
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmit()">
|
||||||
|
<el-row>
|
||||||
|
<h3 class="title">橙单UAA管理系统</h3>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item prop="mobilePhone">
|
||||||
|
<el-input v-model="dataForm.mobilePhone" style="width: 100%;" placeholder="帐号"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item prop="password">
|
||||||
|
<el-input v-model="dataForm.password" style="width: 100%;" type="password" placeholder="密码" show-password></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-button class="login-btn-submit" type="primary" style="width: 100%;" @click="dataFormSubmit()" :loading="isHttpLoading">登录</el-button>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { SystemController } from '@/api';
|
||||||
|
import { mapMutations } from 'vuex';
|
||||||
|
import projectConfig from '@/core/config';
|
||||||
|
import { encrypt } from '@/utils';
|
||||||
|
|
||||||
|
/** UAA 菜单 */
|
||||||
|
const SysMenuList = [
|
||||||
|
{
|
||||||
|
menuId: '1',
|
||||||
|
menuName: '操作员管理',
|
||||||
|
menuType: 1,
|
||||||
|
formRouterName: 'formUaaOperator',
|
||||||
|
showOrder: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
menuId: '2',
|
||||||
|
menuName: '用户管理',
|
||||||
|
menuType: 1,
|
||||||
|
formRouterName: 'formUaaUser',
|
||||||
|
showOrder: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
menuId: '3',
|
||||||
|
menuName: '应用管理',
|
||||||
|
menuType: 1,
|
||||||
|
formRouterName: 'formAuthClient',
|
||||||
|
showOrder: 3
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
dataForm: {
|
||||||
|
mobilePhone: 'admin',
|
||||||
|
password: '123456'
|
||||||
|
},
|
||||||
|
dataRule: {
|
||||||
|
mobilePhone: [
|
||||||
|
{ required: true, message: '帐号不能为空', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
password: [
|
||||||
|
{ required: true, message: '密码不能为空', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
projectName: projectConfig.projectName
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
dataFormSubmit () {
|
||||||
|
this.$refs['dataForm'].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
let params = {
|
||||||
|
loginName: this.dataForm.mobilePhone,
|
||||||
|
password: encrypt(this.dataForm.password)
|
||||||
|
};
|
||||||
|
|
||||||
|
SystemController.login(this, params, null, {showMask: false}).then(data => {
|
||||||
|
this.setMenuList(SysMenuList.filter((item) => {
|
||||||
|
return data.data.isAdmin || item.menuId !== '1';
|
||||||
|
}));
|
||||||
|
this.setUserInfo(data.data);
|
||||||
|
window.sessionStorage.setItem('token', data.data.tokenData);
|
||||||
|
this.setCurrentMenuId(null);
|
||||||
|
this.$router.replace({ name: 'main' });
|
||||||
|
}).catch(e => {});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
...mapMutations(['setUserInfo', 'setMenuList', 'setCurrentMenuId'])
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.setMenuList([]);
|
||||||
|
this.setUserInfo({});
|
||||||
|
window.sessionStorage.removeItem('token');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.login-form {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
height: 100vh;
|
||||||
|
background: url(~@/assets/img/login_bg.jpg) no-repeat 50%, #000;
|
||||||
|
background-size: 100%;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin: 0px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
color: #707070;
|
||||||
|
font-size: 24;
|
||||||
|
text-align: center;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="title">
|
||||||
|
<p>浏览完每个功能过后,自然会发现些与众不同。然而这一切都是<span> 橙单 </span>生成的。</p>
|
||||||
|
</div>
|
||||||
|
<el-row type="flex">
|
||||||
|
<div style="width: 100%;">
|
||||||
|
<el-card class="box-card" shadow="never" :body-style="{padding: '0px 20px'}">
|
||||||
|
<el-collapse v-model="currentItem">
|
||||||
|
<el-collapse-item title="选择我们的 5 个理由" name="1">
|
||||||
|
<ul class="item-list">
|
||||||
|
<li>是真正的生成器,而非脚手架。</li>
|
||||||
|
<li>技术选型、包名、作者署名都由您钦定。</li>
|
||||||
|
<li>手把手教的操作指南和教学视频。</li>
|
||||||
|
<li>详尽、完善、免费、护眼的开发文档。</li>
|
||||||
|
<li>合理、超低价的商业授权。</li>
|
||||||
|
</ul>
|
||||||
|
</el-collapse-item>
|
||||||
|
<el-collapse-item title="我们的技术选型" name="2">
|
||||||
|
<ul class="item-list">
|
||||||
|
<li>Element (Vue) / Ant Design (React) / ECharts / AntV / Axios / Webpack</li>
|
||||||
|
<li>Spring Boot / Spring Cloud / Spring Cloud Alibaba + Mybatis + Jwt</li>
|
||||||
|
<li>Hutool + Guava + Caffeine + Lombok + MapStruct + 通用 mapper</li>
|
||||||
|
<li>Redis + ZooKeeper + Consul + Apollo + XXL-Job + Kafka</li>
|
||||||
|
<li>ELK + PinPoint / SkyWalking + Grafana + Prometheus</li>
|
||||||
|
</ul>
|
||||||
|
</el-collapse-item>
|
||||||
|
<el-collapse-item title="可快速上手的高质量代码" name="3">
|
||||||
|
<ul class="item-list">
|
||||||
|
<li>无任何二次封装,只生成您最懂的代码。</li>
|
||||||
|
<li>遵循阿里巴巴标准的代码规范。</li>
|
||||||
|
<li>主流技术栈恣意组合,对面试大有裨益。</li>
|
||||||
|
<li>产品级代码强度,层次清晰、滴水不漏。</li>
|
||||||
|
<li>15年架构师优化的每一处细节。</li>
|
||||||
|
</ul>
|
||||||
|
</el-collapse-item>
|
||||||
|
<el-collapse-item title="设计理念和未来目标" name="4">
|
||||||
|
<ul class="item-list">
|
||||||
|
<li>前沿的单表组合式设计,使系统拆分SO EASY。</li>
|
||||||
|
<li>先代码,后SQL的原则,让服务扩充更具弹性。</li>
|
||||||
|
<li>全面、实用的日志跟踪和服务监控体系。</li>
|
||||||
|
<li>未来将演化为云原生架构,支持更多开发语言。</li>
|
||||||
|
<li>不会让数据中台成为我们的空白。</li>
|
||||||
|
</ul>
|
||||||
|
</el-collapse-item>
|
||||||
|
</el-collapse>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
<el-card class="box-card" style="min-width: 450px; margin-left: 20px;" shadow="never" :body-style="{padding: '0px 20px'}">
|
||||||
|
<div class="item">
|
||||||
|
<span style="width: 120px;">产品名称</span>
|
||||||
|
<el-tag effect="dark">橙单代码生成器</el-tag>
|
||||||
|
</div>
|
||||||
|
<el-divider></el-divider>
|
||||||
|
<div class="item">
|
||||||
|
<span style="width: 120px;">网站首页</span>
|
||||||
|
<a href="http://101.200.178.51/" target="_blank">http://101.200.178.51/</a>
|
||||||
|
</div>
|
||||||
|
<el-divider></el-divider>
|
||||||
|
<div class="item">
|
||||||
|
<span style="width: 120px;">教学视频</span>
|
||||||
|
<a href="https://www.bilibili.com/video/BV1Wg4y1i7vP" target="_blank">https://www.bilibili.com/video/BV1Wg4y1i7vP</a>
|
||||||
|
</div>
|
||||||
|
<el-divider></el-divider>
|
||||||
|
<div class="item">
|
||||||
|
<span style="width: 120px;">操作指南</span>
|
||||||
|
<a href="http://101.200.178.51/orange-doc/" target="_blank">http://101.200.178.51/orange-doc/</a>
|
||||||
|
</div>
|
||||||
|
<el-divider></el-divider>
|
||||||
|
<div class="item">
|
||||||
|
<span style="width: 120px;">开发文档</span>
|
||||||
|
<a href="http://101.200.178.51/development-doc/" target="_blank">http://101.200.178.51/development-doc/</a>
|
||||||
|
</div>
|
||||||
|
<el-divider></el-divider>
|
||||||
|
<div class="item">
|
||||||
|
<span style="width: 120px;">开源代码</span>
|
||||||
|
<a href="https://gitee.com/orangeform/orange-admin" target="_blank">https://gitee.com/orangeform/orange-admin</a>
|
||||||
|
</div>
|
||||||
|
<el-divider></el-divider>
|
||||||
|
<div class="item">
|
||||||
|
<span style="width: 120px;">联系方式</span>
|
||||||
|
<span>
|
||||||
|
QQ群
|
||||||
|
<a target="_blank" style="margin-left: 5px;"
|
||||||
|
href="//shang.qq.com/wpa/qunwpa?idkey=590857a1b4c587e2be3d66b9a7e2015109772e777c6451c897dee393489b1661">
|
||||||
|
788581363
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<el-divider></el-divider>
|
||||||
|
<div style="width: 100%; text-align: center; padding: 10px;">
|
||||||
|
<img src="../../assets/img/orange-group1.png" />
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
currentItem: ['1', '2', '3', '4']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
>>> .el-collapse {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
>>> .el-divider--horizontal {
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
>>> .el-tag {
|
||||||
|
padding: 0px 30px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '../../assets/style/element-color.scss';
|
||||||
|
.title {
|
||||||
|
border: 1px solid #EDEDED;
|
||||||
|
border-left-width: 5px;
|
||||||
|
border-left-color: $--color-primary;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title p {
|
||||||
|
height: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
font-size: 16px;
|
||||||
|
margin: 0px;
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title p span {
|
||||||
|
font-size: 20px;
|
||||||
|
color: $--color-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-list {
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
.item-list li {
|
||||||
|
margin: 10px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
height: 48px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
module.exports = {
|
||||||
|
devServer: {
|
||||||
|
port: 8085
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
> 1%
|
||||||
|
last 2 versions
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[*.{js,jsx,ts,tsx,vue}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||