vue2-client 1.20.91 → 1.20.93
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs//350/257/267/346/261/202/345/267/245/345/205/267/344/275/277/347/224/250/350/257/264/346/230/216.md +12 -12
- package/package.json +2 -2
- package/src/composables/usePost.js +29 -16
- package/src/constants/crypto.js +5 -0
- package/src/pages/login/Login.vue +2 -9
- package/src/pages/login/LoginV3.vue +2 -9
- package/src/services/api/common.js +1 -1
- package/src/services/api/restTools.js +1 -1
- package/src/utils/EncryptUtil.js +26 -8
- package/src/utils/login.js +49 -13
- package/src/utils/request.js +7 -5
- package/vue.config.js +10 -10
|
@@ -34,7 +34,7 @@ const result = await post('/api/user/save', { name: '张三' })
|
|
|
34
34
|
const result = await post('/api/user/save', { name: '张三' }, {
|
|
35
35
|
globalLoading: '保存中...', // 显示全局 Loading
|
|
36
36
|
dedupe: false, // 关闭请求去重(POST 默认开启)
|
|
37
|
-
showErrorMessage: false // 关闭 code 500 的默认错误提示,由业务自行处理
|
|
37
|
+
showErrorMessage: false // 关闭 code 500 / 其他非 200 的默认错误提示,由业务自行处理
|
|
38
38
|
})
|
|
39
39
|
```
|
|
40
40
|
|
|
@@ -43,7 +43,7 @@ const result = await post('/api/user/save', { name: '张三' }, {
|
|
|
43
43
|
| 参数 | 类型 | 默认值 | 说明 |
|
|
44
44
|
|------|------|--------|------|
|
|
45
45
|
| `globalLoading` | `boolean \| string` | `false` | 是否显示全局 Loading,传字符串可自定义提示文字 |
|
|
46
|
-
| `showErrorMessage` | `boolean` | `true` |
|
|
46
|
+
| `showErrorMessage` | `boolean` | `true` | 对业务 **code 500** 及其他非 200(不含 601)是否显示默认错误提示,设为 `false` 时由业务自行处理 |
|
|
47
47
|
| `dedupe` | `boolean` | `true` | 请求去重开关,POST 请求默认开启 |
|
|
48
48
|
|
|
49
49
|
### 2. get - GET 请求
|
|
@@ -152,13 +152,13 @@ import { runLogic } from '@vue2-client/services/api/common'
|
|
|
152
152
|
// 基础用法(失败时自动弹出右上角错误提示)
|
|
153
153
|
const result = await runLogic('getUserInfo', { userId: 1 }, 'af-system')
|
|
154
154
|
|
|
155
|
-
//
|
|
155
|
+
// 关闭默认错误提示,自行处理失败
|
|
156
156
|
try {
|
|
157
157
|
const result = await runLogic('getUserInfo', { userId: 1 }, 'af-system', false, {
|
|
158
158
|
showErrorMessage: false
|
|
159
159
|
})
|
|
160
160
|
} catch (msg) {
|
|
161
|
-
this.$message.warning(msg) //
|
|
161
|
+
this.$message.warning(msg) // 对 500 及其他非 200 生效;601 等仍会走拦截器默认提示
|
|
162
162
|
}
|
|
163
163
|
```
|
|
164
164
|
|
|
@@ -167,11 +167,11 @@ try {
|
|
|
167
167
|
| 参数 | 类型 | 默认值 | 说明 |
|
|
168
168
|
|------|------|--------|------|
|
|
169
169
|
| `globalLoading` | `boolean \| string` | `false` | 是否显示全局 Loading |
|
|
170
|
-
| `showErrorMessage` | `boolean` | `true` |
|
|
170
|
+
| `showErrorMessage` | `boolean` | `true` | 对业务 **code 500** 及其他非 200(不含 601)是否显示默认错误提示,设为 `false` 时由业务自行处理 |
|
|
171
171
|
| `dedupe` | `boolean` | `true` | 请求去重开关 |
|
|
172
172
|
| `dedupeStrategy` | `string` | 见环境 | 去重策略:`reject` 或 `reuse` |
|
|
173
173
|
|
|
174
|
-
> 说明:默认错误提示由 `request.js` 响应拦截器通过 Ant Design Vue 的 `notification` 展示(右上角)。`showErrorMessage: false`
|
|
174
|
+
> 说明:默认错误提示由 `request.js` 响应拦截器通过 Ant Design Vue 的 `notification` 展示(右上角)。`showErrorMessage: false` 对 **code 500**、**其他非 200**(及 HTTP 500)关闭自动提示;**601**、401/403 等仍按原逻辑提示。请求仍会 `reject`,便于在 `.catch` 或 `try/catch` 中自定义处理。
|
|
175
175
|
|
|
176
176
|
### useRunLogic - 响应式 Hook
|
|
177
177
|
|
|
@@ -214,7 +214,7 @@ export default {
|
|
|
214
214
|
| `serviceName` | `string` | `VUE_APP_SYSTEM_NAME` | 服务名称 |
|
|
215
215
|
| `isDev` | `boolean` | `false` | 是否使用开发环境 API |
|
|
216
216
|
| `globalLoading` | `boolean \| string` | `false` | 是否显示全局 Loading |
|
|
217
|
-
| `showErrorMessage` | `boolean` | `true` |
|
|
217
|
+
| `showErrorMessage` | `boolean` | `true` | 对业务 **code 500** 及其他非 200(不含 601)是否显示默认错误提示,设为 `false` 时由业务自行处理 |
|
|
218
218
|
| `dedupe` | `boolean` | `false` | 请求去重开关 |
|
|
219
219
|
|
|
220
220
|
---
|
|
@@ -390,7 +390,7 @@ const handleSave = async () => {
|
|
|
390
390
|
}
|
|
391
391
|
}
|
|
392
392
|
|
|
393
|
-
//
|
|
393
|
+
// 模式二:需要自定义错误处理(关闭 500 / 其他非 200 的默认 notification)
|
|
394
394
|
const handleSave = async () => {
|
|
395
395
|
const { success, data, error } = await execute(formData, { showErrorMessage: false })
|
|
396
396
|
if (success) {
|
|
@@ -415,9 +415,9 @@ const loadData = async () => {
|
|
|
415
415
|
}
|
|
416
416
|
```
|
|
417
417
|
|
|
418
|
-
### 5.
|
|
418
|
+
### 5. 关闭默认错误提示
|
|
419
419
|
|
|
420
|
-
当接口返回业务 **code 500**(或 HTTP 500)时,拦截器默认会在右上角弹出 `notification
|
|
420
|
+
当接口返回业务 **code 500**、**其他非 200**(或 HTTP 500)时,拦截器默认会在右上角弹出 `notification`。若需由业务自行处理,在请求 `config` 中设置:
|
|
421
421
|
|
|
422
422
|
```javascript
|
|
423
423
|
post('/api/xxx', data, { showErrorMessage: false })
|
|
@@ -427,6 +427,6 @@ useRunLogic('logicName', { showErrorMessage: false })
|
|
|
427
427
|
|
|
428
428
|
**注意:**
|
|
429
429
|
|
|
430
|
-
- `showErrorMessage: false`
|
|
431
|
-
- 不会阻止 Promise 进入 `reject
|
|
430
|
+
- `showErrorMessage: false` 对 **500** 与 **其他非 200** 生效;**601**、401/403 等仍会弹出默认提示。
|
|
431
|
+
- 不会阻止 Promise 进入 `reject`,仅关闭上述场景的自动 notification。
|
|
432
432
|
- 登录过期(401)等系统级 `loginExpire` 弹窗不受此配置影响。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vue2-client",
|
|
3
|
-
"version": "1.20.
|
|
3
|
+
"version": "1.20.93",
|
|
4
4
|
"private": false,
|
|
5
5
|
"scripts": {
|
|
6
6
|
"serve": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve --no-eslint",
|
|
@@ -113,4 +113,4 @@
|
|
|
113
113
|
"not dead",
|
|
114
114
|
"not ie 11"
|
|
115
115
|
]
|
|
116
|
-
}
|
|
116
|
+
}
|
|
@@ -24,7 +24,7 @@ import { post } from '@vue2-client/services/api/restTools'
|
|
|
24
24
|
* @param {string} url - 请求地址
|
|
25
25
|
* @param {object} defaultConfig - 默认配置
|
|
26
26
|
* @param {boolean|string} defaultConfig.globalLoading - 是否显示全局 Loading
|
|
27
|
-
* @param {boolean} defaultConfig.showErrorMessage - 业务 code 500
|
|
27
|
+
* @param {boolean} defaultConfig.showErrorMessage - 业务 code 500 及其他非 200(不含 601)时是否显示默认错误提示(默认 true),设为 false 时由业务自行处理
|
|
28
28
|
* @param {boolean} defaultConfig.dedupe - 是否启用请求去重(POST 默认开启,设为 false 可关闭)
|
|
29
29
|
* @returns {UsePostReturn}
|
|
30
30
|
*
|
|
@@ -47,7 +47,7 @@ import { post } from '@vue2-client/services/api/restTools'
|
|
|
47
47
|
* await execute({ id: 1 })
|
|
48
48
|
* // data 会自动更新,可直接在模板中使用
|
|
49
49
|
*/
|
|
50
|
-
export function usePost
|
|
50
|
+
export function usePost(url, defaultConfig = {}) {
|
|
51
51
|
// 响应式状态
|
|
52
52
|
const state = Vue.observable({
|
|
53
53
|
loading: false,
|
|
@@ -61,7 +61,7 @@ export function usePost (url, defaultConfig = {}) {
|
|
|
61
61
|
* @param {object} config - 本次请求的配置(覆盖默认配置)
|
|
62
62
|
* @returns {Promise<RequestResult>} 统一的结果结构
|
|
63
63
|
*/
|
|
64
|
-
async function execute
|
|
64
|
+
async function execute(params = {}, config = {}) {
|
|
65
65
|
state.loading = true
|
|
66
66
|
state.error = null
|
|
67
67
|
|
|
@@ -80,7 +80,7 @@ export function usePost (url, defaultConfig = {}) {
|
|
|
80
80
|
/**
|
|
81
81
|
* 重置状态
|
|
82
82
|
*/
|
|
83
|
-
function reset
|
|
83
|
+
function reset() {
|
|
84
84
|
state.loading = false
|
|
85
85
|
state.error = null
|
|
86
86
|
state.data = null
|
|
@@ -88,9 +88,15 @@ export function usePost (url, defaultConfig = {}) {
|
|
|
88
88
|
|
|
89
89
|
// 返回响应式属性的 getter,确保在模板中能正确响应
|
|
90
90
|
return {
|
|
91
|
-
get loading
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
get loading() {
|
|
92
|
+
return state.loading
|
|
93
|
+
},
|
|
94
|
+
get error() {
|
|
95
|
+
return state.error
|
|
96
|
+
},
|
|
97
|
+
get data() {
|
|
98
|
+
return state.data
|
|
99
|
+
},
|
|
94
100
|
execute,
|
|
95
101
|
reset
|
|
96
102
|
}
|
|
@@ -117,7 +123,7 @@ export default usePost
|
|
|
117
123
|
* @param {boolean} options.isDev - 是否为开发环境
|
|
118
124
|
* @param {boolean|string} options.globalLoading - 是否显示全局 Loading
|
|
119
125
|
* @param {boolean} options.dedupe - 是否启用请求去重(POST 默认开启,设为 false 可关闭)
|
|
120
|
-
* @param {boolean} options.showErrorMessage - 业务 code 500
|
|
126
|
+
* @param {boolean} options.showErrorMessage - 业务 code 500 及其他非 200(不含 601)时是否显示默认错误提示(默认 true),设为 false 时由业务自行处理
|
|
121
127
|
* @returns {UseRunLogicReturn}
|
|
122
128
|
*
|
|
123
129
|
* @example
|
|
@@ -143,7 +149,7 @@ export default usePost
|
|
|
143
149
|
* isDev: false
|
|
144
150
|
* })
|
|
145
151
|
*/
|
|
146
|
-
export function useRunLogic
|
|
152
|
+
export function useRunLogic(logicName, options = {}) {
|
|
147
153
|
const {
|
|
148
154
|
serviceName = process.env.VUE_APP_SYSTEM_NAME,
|
|
149
155
|
isDev = false,
|
|
@@ -165,7 +171,7 @@ export function useRunLogic (logicName, options = {}) {
|
|
|
165
171
|
* @param {boolean} dev - 是否开发环境
|
|
166
172
|
* @returns {string}
|
|
167
173
|
*/
|
|
168
|
-
function buildUrl
|
|
174
|
+
function buildUrl(svcName, dev) {
|
|
169
175
|
const apiPre = dev ? '/devApi/' : '/api/'
|
|
170
176
|
return `${apiPre}${svcName}/logic/${logicName}`
|
|
171
177
|
}
|
|
@@ -176,7 +182,7 @@ export function useRunLogic (logicName, options = {}) {
|
|
|
176
182
|
* @param {object} overrideOptions - 本次请求的配置(覆盖默认配置)
|
|
177
183
|
* @returns {Promise<RequestResult>} 统一的结果结构
|
|
178
184
|
*/
|
|
179
|
-
async function execute
|
|
185
|
+
async function execute(params = {}, overrideOptions = {}) {
|
|
180
186
|
state.loading = true
|
|
181
187
|
state.error = null
|
|
182
188
|
|
|
@@ -191,7 +197,8 @@ export function useRunLogic (logicName, options = {}) {
|
|
|
191
197
|
const requestConfig = {
|
|
192
198
|
globalLoading: overrideOptions.globalLoading !== undefined ? overrideOptions.globalLoading : globalLoading,
|
|
193
199
|
dedupe: overrideOptions.dedupe !== undefined ? overrideOptions.dedupe : dedupe,
|
|
194
|
-
showErrorMessage:
|
|
200
|
+
showErrorMessage:
|
|
201
|
+
overrideOptions.showErrorMessage !== undefined ? overrideOptions.showErrorMessage : showErrorMessage
|
|
195
202
|
}
|
|
196
203
|
|
|
197
204
|
try {
|
|
@@ -209,16 +216,22 @@ export function useRunLogic (logicName, options = {}) {
|
|
|
209
216
|
/**
|
|
210
217
|
* 重置状态
|
|
211
218
|
*/
|
|
212
|
-
function reset
|
|
219
|
+
function reset() {
|
|
213
220
|
state.loading = false
|
|
214
221
|
state.error = null
|
|
215
222
|
state.data = null
|
|
216
223
|
}
|
|
217
224
|
|
|
218
225
|
return {
|
|
219
|
-
get loading
|
|
220
|
-
|
|
221
|
-
|
|
226
|
+
get loading() {
|
|
227
|
+
return state.loading
|
|
228
|
+
},
|
|
229
|
+
get error() {
|
|
230
|
+
return state.error
|
|
231
|
+
},
|
|
232
|
+
get data() {
|
|
233
|
+
return state.data
|
|
234
|
+
},
|
|
222
235
|
execute,
|
|
223
236
|
reset
|
|
224
237
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 与会话加密对应的 RSA 私钥,与 af-system-vue-web .env 中 VITE_RSA_PRIVATE_KEY 保持一致
|
|
3
|
+
*/
|
|
4
|
+
export const RSA_PRIVATE_KEY =
|
|
5
|
+
'MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIRrmftLDHCQqREEJ132Onu+W3vmFbdF7QD751SrcDDGDTfzuz1zBuElvkHhuDBb7KZkXrCIe+MhvX2IvxcLObl3faX+evYlnfj2HRbF0hIpQLuIq22tL06ZcV5w7wqLxUZRpFElIFm8gZTkUvfKXVuHw89e4daDVhU5hK3GHNGTAgMBAAECgYABiINrFaE1E8pkBYx1JJA5yuhL73aUktfd2TeCU00vFg6kyrWCI85Sa2RKu/6CJNZWeOFgdubEUv7a22tRrNIZb3yUMaqtTwSso78mspIOJqjWXTkTH9WPElfTcdpdIse/lgZtPz6egxkuhadSvwrM9Y6NgusiW/5+x95Ct08iOQJBAN5aK+7uISURvGQj2EaRtgGEd8+d4oHl+BYvvTeG3qSgUikHQW3j0sp4gXPw2kxw6sjVgLFOc4FB6LGqwzOTzokCQQCYdYG8ty3Uo/ebUlNzeJFxHXjy/KvBSytAUzAXkRu3nZrkEaPQsi3dgOkZgk+F1fMDzfQ4EbDIU6xvqOoZXHg7AkATCW9XfoXR8anKfRMoP5Nwn9HOMbtR2cmaxK2TknV/bMZ8AsYETYwfj5+tuIJIJybC2RyykX/sIiN1CqS5xr7ZAkArj19rMRdaKyMi8MnBM1Cy9g3Jt2HHj5ejAGG8SgyWUOShh1y70z0BjcSMMkxQXAncK2s83ekZw7aADM4eQupjAkARRgTwwMOnn3IoKmQusKhZk0uxilZ4Zc2LH6Z4GiWnvteM0W8Zw4Z1lJUcjgQq3dGqL2RdmzeQZ+HgPIOXrZVK'
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
<script>
|
|
56
56
|
import CommonLayout from '@vue2-client/layouts/CommonLayout'
|
|
57
57
|
import { getRoutesConfig, login, V4Login } from '@vue2-client/services/user'
|
|
58
|
+
import { setV4AccessToken } from '@vue2-client/utils/login'
|
|
58
59
|
import { setAuthorization } from '@vue2-client/utils/request'
|
|
59
60
|
import { loadRoutes, funcToRouterOA, funcToRouter } from '@vue2-client/utils/routerUtil'
|
|
60
61
|
import { mapMutations, mapState } from 'vuex'
|
|
@@ -131,7 +132,7 @@ export default {
|
|
|
131
132
|
}
|
|
132
133
|
},
|
|
133
134
|
afterLoginV4 (res) {
|
|
134
|
-
|
|
135
|
+
setV4AccessToken(res)
|
|
135
136
|
let data = res.resources
|
|
136
137
|
if (data.data) {
|
|
137
138
|
data = data.data
|
|
@@ -224,14 +225,6 @@ export default {
|
|
|
224
225
|
const dateAfter = new Date(timestamp)
|
|
225
226
|
setAuthorization({ token: data, expireAt: dateAfter })
|
|
226
227
|
}
|
|
227
|
-
},
|
|
228
|
-
setV4AccessToken (res) {
|
|
229
|
-
localStorage.setItem(ACCESS_TOKEN, res.access_token)
|
|
230
|
-
let timestamp = new Date().getTime()// 当前的时间戳
|
|
231
|
-
timestamp = timestamp + res.expire * 60 * 1000
|
|
232
|
-
// 格式化时间获取年月日, 登陆过期时间
|
|
233
|
-
const dateAfter = new Date(timestamp)
|
|
234
|
-
setAuthorization({ token: res.access_token, expireAt: dateAfter })
|
|
235
228
|
}
|
|
236
229
|
}
|
|
237
230
|
}
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
<script>
|
|
56
56
|
import CommonLayout from '@vue2-client/layouts/CommonLayout'
|
|
57
57
|
import { getRoutesConfig, login, V4Login } from '@vue2-client/services/user'
|
|
58
|
+
import { setV4AccessToken } from '@vue2-client/utils/login'
|
|
58
59
|
import { setAuthorization } from '@vue2-client/utils/request'
|
|
59
60
|
import { loadRoutes, funcToRouterOA, funcToRouter } from '@vue2-client/utils/routerUtil'
|
|
60
61
|
import { mapMutations, mapState } from 'vuex'
|
|
@@ -130,7 +131,7 @@ export default {
|
|
|
130
131
|
}
|
|
131
132
|
},
|
|
132
133
|
afterLoginV4 (res) {
|
|
133
|
-
|
|
134
|
+
setV4AccessToken(res)
|
|
134
135
|
let data = res.resources
|
|
135
136
|
if (data.data) {
|
|
136
137
|
data = data.data
|
|
@@ -223,14 +224,6 @@ export default {
|
|
|
223
224
|
const dateAfter = new Date(timestamp)
|
|
224
225
|
setAuthorization({ token: data, expireAt: dateAfter })
|
|
225
226
|
}
|
|
226
|
-
},
|
|
227
|
-
setV4AccessToken (res) {
|
|
228
|
-
localStorage.setItem(ACCESS_TOKEN, res.access_token)
|
|
229
|
-
let timestamp = new Date().getTime()// 当前的时间戳
|
|
230
|
-
timestamp = timestamp + res.expire * 60 * 1000
|
|
231
|
-
// 格式化时间获取年月日, 登陆过期时间
|
|
232
|
-
const dateAfter = new Date(timestamp)
|
|
233
|
-
setAuthorization({ token: res.access_token, expireAt: dateAfter })
|
|
234
227
|
}
|
|
235
228
|
}
|
|
236
229
|
}
|
|
@@ -182,7 +182,7 @@ export function parseConfig(configContent, configType) {
|
|
|
182
182
|
* @param {boolean} config.dedupe - 是否启用去重(默认 true)
|
|
183
183
|
* @param {string} config.dedupeStrategy - 去重策略:'reject'(拒绝)或 'reuse'(复用结果)
|
|
184
184
|
* @param {boolean|string} config.globalLoading - 是否显示全局 Loading
|
|
185
|
-
* @param {boolean} config.showErrorMessage - 业务 code 500
|
|
185
|
+
* @param {boolean} config.showErrorMessage - 业务 code 500 及其他非 200(不含 601)时是否显示默认错误提示(默认 true),设为 false 时由业务自行处理
|
|
186
186
|
*/
|
|
187
187
|
export function runLogic(logicName, parameter, serviceName = process.env.VUE_APP_SYSTEM_NAME, isDev, config = {}) {
|
|
188
188
|
let apiPre = '/api/'
|
|
@@ -18,7 +18,7 @@ function get (url, parameter) {
|
|
|
18
18
|
* @param parameter 请求参数
|
|
19
19
|
* @param config 配置项
|
|
20
20
|
* @param {boolean|string} config.globalLoading - 是否显示全局 Loading,可传入字符串作为提示文字
|
|
21
|
-
* @param {boolean} config.showErrorMessage - 业务 code 500
|
|
21
|
+
* @param {boolean} config.showErrorMessage - 业务 code 500 及其他非 200(不含 601)时是否显示默认错误提示(默认 true),设为 false 时由业务自行处理
|
|
22
22
|
* @param {boolean} config.dedupe - 是否启用请求去重(POST 默认开启,设为 false 可关闭)
|
|
23
23
|
* @param {string} config.dedupeStrategy - 去重策略:'reject'(拒绝,默认)或 'reuse'(复用结果)
|
|
24
24
|
* @returns {Promise<AxiosResponse<T>>}
|
package/src/utils/EncryptUtil.js
CHANGED
|
@@ -7,7 +7,7 @@ export default {
|
|
|
7
7
|
* @param word
|
|
8
8
|
* @returns {*}
|
|
9
9
|
*/
|
|
10
|
-
AESEncrypt
|
|
10
|
+
AESEncrypt(word, encryKey) {
|
|
11
11
|
const key = CryptoJS.enc.Utf8.parse(encryKey)
|
|
12
12
|
const srcs = CryptoJS.enc.Utf8.parse(word)
|
|
13
13
|
const encrypted = CryptoJS.AES.encrypt(srcs, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 })
|
|
@@ -18,7 +18,7 @@ export default {
|
|
|
18
18
|
* @param word
|
|
19
19
|
* @returns {*}
|
|
20
20
|
*/
|
|
21
|
-
AESDecrypt
|
|
21
|
+
AESDecrypt(word, encryKey) {
|
|
22
22
|
const key = CryptoJS.enc.Utf8.parse(encryKey)
|
|
23
23
|
const decrypt = CryptoJS.AES.decrypt(word, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 })
|
|
24
24
|
const ret = CryptoJS.enc.Utf8.stringify(decrypt).toString()
|
|
@@ -33,7 +33,7 @@ export default {
|
|
|
33
33
|
* @param word
|
|
34
34
|
* @returns {*}
|
|
35
35
|
*/
|
|
36
|
-
RSAEncrypt
|
|
36
|
+
RSAEncrypt(word) {
|
|
37
37
|
const encrypt = new RsaEncryptJS()
|
|
38
38
|
encrypt.setPublicKey('MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqPvovSfXcwBbW8cKMCgwqNpsYuzF8RPAPFb7LGsnVo44JhM/xxzDyzoYtdfNmtbIuKVi9PzIsyp6rg+09gbuI6UGwBZ5DWBDBMqv5MPdOF5dCQkB2Bbr5yPfURPENypUz+pBFBg41d+BC+rwRiXELwKy7Y9caD/MtJyHydj8OUwIDAQAB')
|
|
39
39
|
const resdata = encrypt.encrypt(word)
|
|
@@ -44,14 +44,32 @@ export default {
|
|
|
44
44
|
* @param word
|
|
45
45
|
* @returns {*}
|
|
46
46
|
*/
|
|
47
|
-
RSADecrypt
|
|
47
|
+
RSADecrypt(word) {
|
|
48
48
|
const encrypt = new RsaEncryptJS()
|
|
49
49
|
encrypt.setPrivateKey('MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKo++i9J9dzAFtbxwowKDCo2mxi7MXxE8A8VvssaydWjjgmEz/HHMPLOhi1182a1si4pWL0/MizKnquD7T2Bu4jpQbAFnkNYEMEyq/kw904Xl0JCQHYFuvnI99RE8Q3KlTP6kEUGDjV34EL6vBGJcQvArLtj1xoP8y0nIfJ2Pw5TAgMBAAECgYAGGB8IllMwxceLhjf6n1l0IWRH7FuHIUieoZ6k0p6rASHSgWiYNRMxfecbtX8zDAoG0QAWNi7rn40ygpR5gS1fWDAKhmnhKgQIT6wW0VmD4hraaeyP78iy8BLhlvblri2nCPIhDH5+l96v7D47ZZi3ZSOzcj89s1eS/k7/N4peEQJBAPEtGGJY+lBoCxQMhGyzuzDmgcS1Un1ZE2pt+XNCVl2b+T8fxWJH3tRRR8wOY5uvtPiK1HM/IjT0T5qwQeH8Yk0CQQC0tcv3d/bDb7bOe9QzUFDQkUSpTdPWAgMX2OVPxjdq3Sls9oA5+fGNYEy0OgyqTjde0b4iRzlD1O0OhLqPSUMfAkEAh5FIvqezdRU2/PsYSR4yoAdCdLdT+h/jGRVefhqQ/6eYUJJkWp15tTFHQX3pIe9/s6IeT/XyHYAjaxmevxAmlQJBAKSdhvQjf9KAjZKDEsa7vyJ/coCXuQUWSCMNHbcR5aGfXgE4e45UtUoIE1eKGcd6AM6LWhx3rR6xdFDpb9je8BkCQB0SpevGfOQkMk5i8xkEt9eeYP0fi8nv6eOUcK96EXbzs4jV2SAoQJ9oJegPtPROHbhIvVUmNQTbuP10Yjg59+8=')
|
|
50
50
|
const resdata = encrypt.decrypt(word)
|
|
51
51
|
return JSON.parse(resdata.toString())
|
|
52
52
|
},
|
|
53
|
+
/**
|
|
54
|
+
* RSA 私钥解密,返回明文字符串(不做 JSON 解析)
|
|
55
|
+
*
|
|
56
|
+
* @param {string} encryptedData Base64 密文
|
|
57
|
+
* @param {string} privateKey PKCS#8 格式的私钥
|
|
58
|
+
* @returns {string|null} 解密失败时返回 null
|
|
59
|
+
*/
|
|
60
|
+
RSADecryptRaw(encryptedData, privateKey) {
|
|
61
|
+
try {
|
|
62
|
+
const encrypt = new RsaEncryptJS()
|
|
63
|
+
encrypt.setPrivateKey(privateKey)
|
|
64
|
+
const decrypted = encrypt.decrypt(encryptedData)
|
|
65
|
+
if (!decrypted) return null
|
|
66
|
+
return decrypted
|
|
67
|
+
} catch {
|
|
68
|
+
return null
|
|
69
|
+
}
|
|
70
|
+
},
|
|
53
71
|
|
|
54
|
-
AESEncryptCBC
|
|
72
|
+
AESEncryptCBC(data, CRYPTO_KEY) {
|
|
55
73
|
// 生成随机IV(每次加密不同)
|
|
56
74
|
const iv = CryptoJS.lib.WordArray.random(16)
|
|
57
75
|
|
|
@@ -79,7 +97,7 @@ export default {
|
|
|
79
97
|
* @param hexKey 十六进制格式的加密密钥
|
|
80
98
|
* @returns 解密后的原始字符串
|
|
81
99
|
*/
|
|
82
|
-
AESDecryptCBC
|
|
100
|
+
AESDecryptCBC(combinedText, hexKey) {
|
|
83
101
|
try {
|
|
84
102
|
// 分离 IV 和 密文
|
|
85
103
|
const parts = combinedText.split(':')
|
|
@@ -114,7 +132,7 @@ export default {
|
|
|
114
132
|
* @param hexKey 十六进制格式的密钥
|
|
115
133
|
* @returns 解密后的字符串,失败时返回null
|
|
116
134
|
*/
|
|
117
|
-
safeAESDecryptCBC
|
|
135
|
+
safeAESDecryptCBC(combinedText, hexKey) {
|
|
118
136
|
try {
|
|
119
137
|
return this.AESDecryptCBC(combinedText, hexKey)
|
|
120
138
|
} catch {
|
|
@@ -129,7 +147,7 @@ export default {
|
|
|
129
147
|
* @param sessionKey 会话密钥
|
|
130
148
|
* @returns 解密后的数据,失败时返回原数据
|
|
131
149
|
*/
|
|
132
|
-
decryptResponse
|
|
150
|
+
decryptResponse(responseData, sessionKey) {
|
|
133
151
|
try {
|
|
134
152
|
let dataStr = ''
|
|
135
153
|
|
package/src/utils/login.js
CHANGED
|
@@ -9,9 +9,12 @@ import { message } from 'ant-design-vue'
|
|
|
9
9
|
import {
|
|
10
10
|
ACCESS_TOKEN,
|
|
11
11
|
V4_ACCESS_TOKEN,
|
|
12
|
+
V4_SESSION_KEY,
|
|
12
13
|
} from '@vue2-client/store/mutation-types'
|
|
13
14
|
import { setAuthorization } from '@vue2-client/utils/request'
|
|
14
15
|
import { loginGen } from '@vue2-client/base-client/plugins/GetLoginInfoService'
|
|
16
|
+
import { RSA_PRIVATE_KEY } from '@vue2-client/constants/crypto'
|
|
17
|
+
import EncryptUtil from '@vue2-client/utils/EncryptUtil'
|
|
15
18
|
// 认证类型
|
|
16
19
|
const AUTH_TYPE = {
|
|
17
20
|
BEARER: 'Bearer',
|
|
@@ -21,7 +24,7 @@ const AUTH_TYPE = {
|
|
|
21
24
|
AUTH2: 'auth2',
|
|
22
25
|
}
|
|
23
26
|
|
|
24
|
-
export function checkSingleAuthorization
|
|
27
|
+
export function checkSingleAuthorization(authType = AUTH_TYPE.BEARER, token) {
|
|
25
28
|
switch (authType) {
|
|
26
29
|
case AUTH_TYPE.BEARER:
|
|
27
30
|
if (localStorage.getItem(V4_ACCESS_TOKEN)) {
|
|
@@ -39,7 +42,7 @@ export function checkSingleAuthorization (authType = AUTH_TYPE.BEARER, token) {
|
|
|
39
42
|
return false
|
|
40
43
|
}
|
|
41
44
|
|
|
42
|
-
function setSingleAuthorization
|
|
45
|
+
function setSingleAuthorization(auth, authType = AUTH_TYPE.BEARER) {
|
|
43
46
|
switch (authType) {
|
|
44
47
|
case AUTH_TYPE.BEARER:
|
|
45
48
|
localStorage.setItem(V4_ACCESS_TOKEN, 'Bearer ' + auth.token)
|
|
@@ -52,7 +55,7 @@ function setSingleAuthorization (auth, authType = AUTH_TYPE.BEARER) {
|
|
|
52
55
|
}
|
|
53
56
|
}
|
|
54
57
|
|
|
55
|
-
function setAccessToken
|
|
58
|
+
function setAccessToken(data) {
|
|
56
59
|
if (data) {
|
|
57
60
|
localStorage.setItem(ACCESS_TOKEN, data)
|
|
58
61
|
let timestamp = new Date().getTime() // 当前的时间戳
|
|
@@ -63,7 +66,7 @@ function setAccessToken (data) {
|
|
|
63
66
|
}
|
|
64
67
|
}
|
|
65
68
|
|
|
66
|
-
function afterGeneral
|
|
69
|
+
function afterGeneral(result, options) {
|
|
67
70
|
return new Promise((resolve) => {
|
|
68
71
|
const { password, store } = options
|
|
69
72
|
const user = Object.assign(
|
|
@@ -93,7 +96,7 @@ function afterGeneral (result, options) {
|
|
|
93
96
|
})
|
|
94
97
|
}
|
|
95
98
|
|
|
96
|
-
function afterLogin
|
|
99
|
+
function afterLogin(res, options) {
|
|
97
100
|
const { name, password, store, router, pathname } = options
|
|
98
101
|
const setting = store.state.setting
|
|
99
102
|
const loginRes = res.states
|
|
@@ -138,7 +141,7 @@ function afterLogin (res, options) {
|
|
|
138
141
|
}
|
|
139
142
|
}
|
|
140
143
|
|
|
141
|
-
function afterLoginV4
|
|
144
|
+
function afterLoginV4(res, option) {
|
|
142
145
|
const { router, pathname } = option
|
|
143
146
|
setV4AccessToken(res)
|
|
144
147
|
let data = res.resources
|
|
@@ -154,16 +157,49 @@ function afterLoginV4 (res, option) {
|
|
|
154
157
|
})
|
|
155
158
|
}
|
|
156
159
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
160
|
+
function unwrapV4LoginPayload(res) {
|
|
161
|
+
if (!res || typeof res !== 'object') return null
|
|
162
|
+
if (res.access_token !== undefined && res.access_token !== null) return res
|
|
163
|
+
if (
|
|
164
|
+
res.data &&
|
|
165
|
+
typeof res.data === 'object' &&
|
|
166
|
+
res.data.access_token !== undefined &&
|
|
167
|
+
res.data.access_token !== null
|
|
168
|
+
) {
|
|
169
|
+
return res.data
|
|
170
|
+
}
|
|
171
|
+
return null
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function getWebConfigFromStorage() {
|
|
175
|
+
try {
|
|
176
|
+
const str = localStorage.getItem(process.env.VUE_APP_WEB_CONFIG_KEY)
|
|
177
|
+
return str ? JSON.parse(str) : {}
|
|
178
|
+
} catch {
|
|
179
|
+
return {}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** 解析登录接口返回的 session 并写入 v4-session-key(受 webConfig.requestEncrypt 控制) */
|
|
184
|
+
export function setV4SessionKey(res) {
|
|
185
|
+
const webConfig = getWebConfigFromStorage()
|
|
186
|
+
if (!res?.session || !webConfig?.setting?.requestEncrypt) return
|
|
187
|
+
const sessionKey = EncryptUtil.RSADecryptRaw(res.session, RSA_PRIVATE_KEY)
|
|
188
|
+
if (sessionKey) localStorage.setItem(V4_SESSION_KEY, sessionKey)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function setV4AccessToken(res) {
|
|
192
|
+
const payload = unwrapV4LoginPayload(res)
|
|
193
|
+
if (!payload?.access_token) return
|
|
194
|
+
localStorage.setItem(ACCESS_TOKEN, payload.access_token)
|
|
195
|
+
let timestamp = new Date().getTime() // 当前的时间戳
|
|
196
|
+
timestamp += (payload.expire ?? 0) * 60 * 1000
|
|
162
197
|
const dateAfter = new Date(timestamp)
|
|
163
|
-
setAuthorization({ token:
|
|
198
|
+
setAuthorization({ token: payload.access_token, expireAt: dateAfter })
|
|
199
|
+
setV4SessionKey(payload)
|
|
164
200
|
}
|
|
165
201
|
|
|
166
|
-
export function startLogin
|
|
202
|
+
export function startLogin(options) {
|
|
167
203
|
const { name, password, store } = options
|
|
168
204
|
const setting = store.state.setting
|
|
169
205
|
switch (setting.compatible) {
|
package/src/utils/request.js
CHANGED
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
let isReloginShow
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
* 业务 code 500
|
|
33
|
+
* 业务 code 500 及其他非 200(不含 601)时是否显示默认错误提示(notification)
|
|
34
34
|
* @param {import('axios').AxiosRequestConfig} [config]
|
|
35
35
|
* @returns {boolean}
|
|
36
36
|
*/
|
|
@@ -401,10 +401,12 @@ function loadInterceptors() {
|
|
|
401
401
|
description: msg
|
|
402
402
|
})
|
|
403
403
|
} else if (code !== 200) {
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
404
|
+
if (shouldShowErrorMessage(res.config)) {
|
|
405
|
+
notification.error({
|
|
406
|
+
message: '失败',
|
|
407
|
+
description: msg
|
|
408
|
+
})
|
|
409
|
+
}
|
|
408
410
|
} else {
|
|
409
411
|
// 请求成功,通知复用的请求并返回数据
|
|
410
412
|
if (requestKey) {
|
package/vue.config.js
CHANGED
|
@@ -11,13 +11,13 @@ const productionGzipExtensions = ['js', 'css']
|
|
|
11
11
|
const isProd = process.env.NODE_ENV === 'production'
|
|
12
12
|
|
|
13
13
|
// v4 产品演示
|
|
14
|
-
const liuli = '
|
|
15
|
-
const v3Server = '
|
|
16
|
-
const geoserver = '
|
|
14
|
+
const liuli = 'https://192.168.50.105:31467'
|
|
15
|
+
const v3Server = 'https://192.168.50.105:31467'
|
|
16
|
+
const geoserver = 'https://192.168.50.105:31467'
|
|
17
17
|
// const gateway = 'http://192.168.50.67:31467'
|
|
18
18
|
// const testUpload = 'http://123.60.214.109:8406'
|
|
19
19
|
const OSSServerDev = 'http://192.168.50.67:30351'
|
|
20
|
-
const revenue = '
|
|
20
|
+
const revenue = 'https://192.168.50.105:31467'
|
|
21
21
|
// const revenue = 'http://127.0.0.1:31467'
|
|
22
22
|
// const OSSServerProd = 'http://192.168.50.67:31351'
|
|
23
23
|
// const testUploadLocal = 'http://127.0.0.1:9001'
|
|
@@ -225,13 +225,13 @@ module.exports = {
|
|
|
225
225
|
css: {
|
|
226
226
|
extract: !isProd
|
|
227
227
|
? {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
228
|
+
filename: 'css/[name].css',
|
|
229
|
+
chunkFilename: 'css/[name].css',
|
|
230
|
+
ignoreOrder: true
|
|
231
|
+
}
|
|
232
232
|
: {
|
|
233
|
-
|
|
234
|
-
|
|
233
|
+
ignoreOrder: true
|
|
234
|
+
},
|
|
235
235
|
loaderOptions: {
|
|
236
236
|
less: {
|
|
237
237
|
lessOptions: {
|