haiwei-ui 1.3.1 → 1.3.3

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.
@@ -1,5 +1,6 @@
1
1
  <template>
2
- <nm-form-dialog ref="form" title="修改密码" class="nm-update-password" width="400px" icon="password" :model="model" :rules="rules" :action="updatePassword" :visible.sync="visible_" success-msg-text="修改成功" @success="logout">
2
+ <nm-form-dialog ref="form" title="修改密码" class="nm-update-password" width="400px" icon="password" :model="model"
3
+ :rules="rules" :action="updatePassword" :visible.sync="visible_" success-msg-text="修改成功" @success="logout">
3
4
  <el-alert title="提示" type="warning" description="密码修改成功后,需要重新登录" show-icon :closable="false"></el-alert>
4
5
  <el-row>
5
6
  <el-col :span="18" :offset="2">
@@ -17,56 +18,57 @@
17
18
  </nm-form-dialog>
18
19
  </template>
19
20
  <script>
20
- import visible from '../../mixins/components/visible.js'
21
- import { mapState, mapActions } from 'vuex'
21
+ import visible from '../../mixins/components/visible.js'
22
+ import { mapState, mapActions } from 'vuex'
22
23
 
23
- export default {
24
- name: 'UpdatePassword',
25
- mixins: [visible],
26
- data() {
27
- // 密码验证
28
- const validator = (rule, value, callback) => {
29
- if (value === '') {
30
- callback(new Error('请输入确认密码'))
31
- } else if (value !== this.model.newPassword) {
32
- callback(new Error('两次输入密码不一致!'))
33
- } else {
34
- callback()
35
- }
24
+ export default {
25
+ name: 'UpdatePassword',
26
+ mixins: [visible],
27
+ data() {
28
+ // 密码验证
29
+ const validator = (rule, value, callback) => {
30
+ if (value === '') {
31
+ callback(new Error('请输入确认密码'))
32
+ } else if (value !== this.model.newPassword) {
33
+ callback(new Error('两次输入密码不一致!'))
34
+ } else {
35
+ callback()
36
36
  }
37
- return {
38
- model: {
39
- oldPassword: '',
40
- newPassword: '',
41
- confirmPassword: ''
42
- },
43
- rules: {
44
- oldPassword: [{ required: true, message: '请输入原密码' }],
45
- newPassword: [
46
- { required: true, message: '请输入新密码' },
47
- { min: 6, message: '密码长度不能小于6' }
48
- ],
49
- confirmPassword: [{ validator }]
50
- }
37
+ }
38
+ return {
39
+ model: {
40
+ oldPassword: '',
41
+ newPassword: '',
42
+ confirmPassword: ''
43
+ },
44
+ rules: {
45
+ oldPassword: [{ required: true, message: '请输入原密码' }],
46
+ newPassword: [
47
+ { required: true, message: '请输入新密码' },
48
+ { min: 6, message: '密码长度不能小于6' }
49
+ ],
50
+ confirmPassword: [{ validator }]
51
51
  }
52
- },
53
- computed: {
54
- ...mapState('app/system', { updatePassword: s => s.actions.updatePassword })
55
- },
56
- methods: {
57
- ...mapActions('app/system', ['logout'])
58
52
  }
53
+ },
54
+ computed: {
55
+ ...mapState('app/system', { updatePassword: s => s.actions.updatePassword })
56
+ },
57
+ methods: {
58
+ ...mapActions('app/system', ['logout'])
59
59
  }
60
+ }
60
61
  </script>
61
62
  <style lang="scss" scoped>
62
- .nm-update-password {
63
- .el-alert {
64
- margin-top: -5px;
65
- margin-bottom: 10px;
66
- line-height: 15px;
67
- }
68
- .el-visible__footer {
69
- line-height: 15px;
70
- }
63
+ .nm-update-password {
64
+ .el-alert {
65
+ margin-top: -5px;
66
+ margin-bottom: 10px;
67
+ line-height: 15px;
68
+ }
69
+
70
+ .el-visible__footer {
71
+ line-height: 15px;
71
72
  }
73
+ }
72
74
  </style>
@@ -8,7 +8,7 @@
8
8
  border-style: solid;
9
9
  border-top: 1px solid $border-color2;
10
10
 
11
- > #{$prefix}box-header {
11
+ >#{$prefix}box-header {
12
12
  padding: 0 5px;
13
13
  display: flex;
14
14
  align-items: stretch;
@@ -62,10 +62,12 @@
62
62
 
63
63
  &.is-disabled {
64
64
  cursor: not-allowed;
65
+
65
66
  span {
66
67
  color: #c0c4cc;
67
68
  }
68
69
  }
70
+
69
71
  &:not(.is-disabled):hover {
70
72
  color: $text-color1;
71
73
  transform: scale(1.2);
@@ -74,21 +76,21 @@
74
76
  }
75
77
  }
76
78
 
77
- > #{$prefix}box-dialog {
79
+ >#{$prefix}box-dialog {
78
80
  position: relative;
79
81
  border-bottom-left-radius: 3px;
80
82
  border-bottom-right-radius: 3px;
81
83
  @include flex-column();
82
84
  flex-grow: 1;
83
85
 
84
- > #{$prefix}box-content {
86
+ >#{$prefix}box-content {
85
87
  position: relative;
86
88
  padding: 10px;
87
89
  flex-grow: 1;
88
90
  box-sizing: border-box;
89
91
  }
90
92
 
91
- > #{$prefix}box-footer {
93
+ >#{$prefix}box-footer {
92
94
  padding: 0 10px;
93
95
  flex-shrink: 0;
94
96
  flex-grow: 0;
@@ -113,8 +115,8 @@
113
115
  }
114
116
 
115
117
  &.has-height {
116
- > #{$prefix}box-dialog {
117
- > #{$prefix}box-content {
118
+ >#{$prefix}box-dialog {
119
+ >#{$prefix}box-content {
118
120
  position: absolute;
119
121
  padding-left: 0;
120
122
  padding-right: 0;
@@ -124,8 +126,8 @@
124
126
  #{$prefix}box-wrapper {
125
127
  height: 100%;
126
128
 
127
- > &-scrollbar {
128
- > .el-scrollbar__wrap {
129
+ >&-scrollbar {
130
+ >.el-scrollbar__wrap {
129
131
  padding-left: 10px;
130
132
  padding-right: 10px;
131
133
  }
@@ -147,13 +149,13 @@
147
149
  &.page {
148
150
  height: 100%;
149
151
 
150
- > #{$prefix}box-dialog {
152
+ >#{$prefix}box-dialog {
151
153
  padding: 0;
152
154
 
153
- > #{$prefix}box-content {
155
+ >#{$prefix}box-content {
154
156
  padding: 0;
155
157
 
156
- > #{$prefix}box-wrapper {
158
+ >#{$prefix}box-wrapper {
157
159
  position: absolute;
158
160
  width: 100%;
159
161
  height: 100%;
@@ -167,11 +169,11 @@
167
169
  }
168
170
 
169
171
  &.no-padding {
170
- > #{$prefix}box-dialog {
171
- > #{$prefix}box-content {
172
+ >#{$prefix}box-dialog {
173
+ >#{$prefix}box-content {
172
174
  padding: 0 !important;
173
175
 
174
- > #{$prefix}box-wrapper {
176
+ >#{$prefix}box-wrapper {
175
177
  .el-scrollbar__view {
176
178
  padding: 0 !important;
177
179
  }
@@ -209,4 +211,4 @@
209
211
  font-weight: 600;
210
212
  }
211
213
  }
212
- }
214
+ }
@@ -0,0 +1,355 @@
1
+ import axios from 'axios'
2
+ import qs from 'qs'
3
+ import dayjs from 'dayjs'
4
+ import token from './token'
5
+ import { Message, MessageBox } from 'element-ui'
6
+ import { store } from '../store'
7
+ import { router } from '../router'
8
+
9
+ axios.defaults.headers.post['Content-Type'] = 'application/json'
10
+ axios.defaults.headers.put['Content-Type'] = 'application/json'
11
+
12
+ function Http() {
13
+ this.axios = axios
14
+ }
15
+
16
+ // 序列化参数为Url形式
17
+ Http.prototype.stringify = params => {
18
+ return qs.stringify(params, {
19
+ allowDots: true
20
+ })
21
+ }
22
+
23
+ Http.prototype.post = (url, params, config) => {
24
+ return axios.post(url, params, config)
25
+ }
26
+
27
+ Http.prototype.get = (url, params, config) => {
28
+ const config_ = Object.assign({}, config, {
29
+ // 参数
30
+ params,
31
+ // 修改参数序列化方法
32
+ paramsSerializer: p => {
33
+ // 使用逗号分隔参数
34
+ return qs.stringify(p, {
35
+ allowDots: true
36
+ })
37
+ }
38
+ })
39
+ return axios.get(url, config_)
40
+ }
41
+
42
+ Http.prototype.delete = (url, params, config) => {
43
+ const config_ = Object.assign({}, config, {
44
+ // 参数
45
+ params,
46
+ // 修改参数序列化方法
47
+ paramsSerializer: p => {
48
+ // 使用逗号分隔参数
49
+ return qs.stringify(p, {
50
+ allowDots: true
51
+ })
52
+ }
53
+ })
54
+ return axios.delete(url, config_)
55
+ }
56
+
57
+ Http.prototype.put = (url, params, config) => {
58
+ return axios.put(url, params, config)
59
+ }
60
+
61
+ Http.prototype.download = (url, params, config) => {
62
+ const config_ = Object.assign({ responseType: 'blob' }, config, {
63
+ // 参数
64
+ params,
65
+ // 修改参数序列化方法
66
+ paramsSerializer: p => {
67
+ // 使用逗号分隔参数
68
+ return qs.stringify(p, {
69
+ allowDots: true
70
+ })
71
+ }
72
+ })
73
+ return axios.get(url, config_)
74
+ }
75
+
76
+ Http.prototype.preview = (url, params, config) => {
77
+ const config_ = Object.assign({ responseType: 'blob', headers: { preview: true } }, config, {
78
+ // 参数
79
+ params,
80
+ // 修改参数序列化方法
81
+ paramsSerializer: p => {
82
+ // 使用逗号分隔参数
83
+ return qs.stringify(p, {
84
+ allowDots: true
85
+ })
86
+ }
87
+ })
88
+ return axios.get(url, config_)
89
+ }
90
+
91
+ Http.prototype.export = (url, params, config) => {
92
+ return axios.post(url, params, Object.assign({ responseType: 'blob' }, config))
93
+ }
94
+
95
+ // 通用CRUD接口地址
96
+ Http.prototype.crud = root => {
97
+ if (!root.endsWith('/')) {
98
+ root += '/'
99
+ }
100
+ return {
101
+ query(params) {
102
+ return $http.get(`${root}query`, params)
103
+ },
104
+ add(params) {
105
+ return $http.post(`${root}add`, params)
106
+ },
107
+ remove(id) {
108
+ return $http.delete(`${root}delete`, { id })
109
+ },
110
+ edit(id) {
111
+ return $http.get(`${root}edit`, { id })
112
+ },
113
+ update(params) {
114
+ return $http.post(`${root}update`, params)
115
+ }
116
+ }
117
+ }
118
+
119
+ // 设为全局属性$http
120
+ if (!window.$http) window.$http = new Http()
121
+
122
+ // 消息提醒显示时长(ms)
123
+ const messageDuration = 1500
124
+ //是否显示了账户在其他地方登录的提示框
125
+ let showLoginOnOtherPlaces = false
126
+
127
+ //处理文件下载请求
128
+ const handleDownload = response => {
129
+ //如果返回的是application/json,则表示返回的是json,没有要下载的问题,可能是逻辑处理失败
130
+ if (response.data.type === 'application/json') {
131
+ var reader = new FileReader()
132
+ reader.onload = e => {
133
+ var data = JSON.parse(e.target.result)
134
+ if (data.code === 1) {
135
+ return data.data
136
+ } else {
137
+ Message.error({
138
+ message: data.msg,
139
+ showClose: true,
140
+ duration: messageDuration
141
+ })
142
+ return
143
+ }
144
+ }
145
+ reader.readAsText(response.data)
146
+ return
147
+ }
148
+
149
+ const url = window.URL.createObjectURL(response.data)
150
+
151
+ // 如果是预览直接返回
152
+ if (response.config.headers['preview']) return url
153
+
154
+ let fileName = ''
155
+ // 如果响应头包含'content-disposition'属性,则从该属性中获取文件名称
156
+ let cd = response.headers['content-disposition']
157
+ if (cd) {
158
+ fileName = decodeURI(cd.split("''")[1])
159
+ }
160
+
161
+ //如果文件名不存在,则使用时间戳
162
+ if (!fileName) {
163
+ fileName = dayjs().format('YYYYMMDDHHMMSSS')
164
+ }
165
+
166
+ //通过模拟a标签点击事件下载文件
167
+ const link = document.createElement('a')
168
+ link.href = url
169
+ link.setAttribute('download', fileName)
170
+ document.body.appendChild(link)
171
+ link.click()
172
+ document.body.removeChild(link)
173
+ }
174
+
175
+ //刷新令牌
176
+ const refreshToken = () => {
177
+ let t = token.get()
178
+ if (t && t.refreshToken) {
179
+ return store.state.app.system.actions.refreshToken(t.refreshToken)
180
+ }
181
+
182
+ Promise.reject('refresh token error')
183
+ }
184
+
185
+ // 初始化
186
+ export default config => {
187
+ // 接口根路径
188
+ axios.defaults.baseURL = config.baseUrl
189
+
190
+ // 拦截请求
191
+ axios.interceptors.request.use(
192
+ config => {
193
+ let t = token.get()
194
+ if (t && t.accessToken) {
195
+ config.headers.Authorization = 'Bearer ' + t.accessToken
196
+ }
197
+
198
+ // 开发环境下打印请求日志
199
+ if (process.env.NODE_ENV === 'development') {
200
+ console.group(`[API请求] ${config.method.toUpperCase()} ${config.url}`)
201
+ console.log('请求配置:', {
202
+ 方法: config.method,
203
+ URL: config.url,
204
+ 参数: config.params,
205
+ 数据: config.data,
206
+ 头信息: config.headers
207
+ })
208
+ console.groupEnd()
209
+ }
210
+
211
+ return config
212
+ },
213
+ function(error) {
214
+ // 开发环境下打印请求错误日志
215
+ if (process.env.NODE_ENV === 'development') {
216
+ console.error('[请求拦截器错误]:', error)
217
+ }
218
+ return Promise.reject(error)
219
+ }
220
+ )
221
+
222
+ // 响应前拦截器
223
+ axios.interceptors.response.use(
224
+ response => {
225
+ const { config } = response
226
+
227
+ // 开发环境下打印响应成功日志
228
+ if (process.env.NODE_ENV === 'development') {
229
+ console.group(`[API响应] ${config.method.toUpperCase()} ${config.url}`)
230
+ console.log('响应信息:', {
231
+ 状态码: response.status,
232
+ 状态文本: response.statusText,
233
+ 数据: response.data,
234
+ 头信息: response.headers
235
+ })
236
+ console.groupEnd()
237
+ }
238
+
239
+ // 文件下载/预览
240
+ if (config.responseType && config.responseType === 'blob') {
241
+ return handleDownload(response)
242
+ }
243
+
244
+ if (response.data.code === 1) {
245
+ return response.data.data
246
+ } else if (response.data.code === 0 && !config.noErrorMsg) {
247
+ Message.error({
248
+ message: response.data.msg,
249
+ showClose: true,
250
+ duration: messageDuration
251
+ })
252
+ return Promise.reject(response.data.msg)
253
+ } else {
254
+ return response.data
255
+ }
256
+ },
257
+ error => {
258
+ // 开发环境下打印响应错误日志
259
+ if (process.env.NODE_ENV === 'development') {
260
+ const method = error.config && error.config.method ? error.config.method.toUpperCase() : 'UNKNOWN'
261
+ const url = error.config && error.config.url ? error.config.url : 'unknown'
262
+ const status = error.response && error.response.status
263
+ const responseData = error.response && error.response.data
264
+
265
+ console.group(`[API错误] ${method} ${url}`)
266
+ console.log('错误信息:', {
267
+ 状态码: status,
268
+ 错误消息: error.message,
269
+ 响应数据: responseData,
270
+ 请求配置: error.config
271
+ })
272
+ console.groupEnd()
273
+ }
274
+
275
+ let currentRoute = router.currentRoute
276
+ let redirect = currentRoute.name !== 'login' ? currentRoute.fullPath : '/' // 跳转页面
277
+ if (error && error.response) {
278
+ switch (error.response.status) {
279
+ case 401:
280
+ return refreshToken()
281
+ .then(data => {
282
+ //重新初始化令牌
283
+ store.commit('app/token/init', data)
284
+ //重新发一起一次上次的的请求
285
+ error.config.headers.Authorization = 'Bearer ' + data.accessToken
286
+ return axios.request(error.config)
287
+ })
288
+ .catch(() => {
289
+ // 如果刷新失败,需要删除token并跳转到登录页面
290
+ token.remove()
291
+ router.push({
292
+ name: 'login',
293
+ query: {
294
+ redirect
295
+ }
296
+ })
297
+ })
298
+ case 403:
299
+ store.dispatch(
300
+ 'app/page/close',
301
+ {
302
+ fullPath: currentRoute.path,
303
+ router: router,
304
+ to: {
305
+ name: 'error403'
306
+ }
307
+ },
308
+ { root: true }
309
+ )
310
+ break
311
+ case 622:
312
+ //单账户登录功能
313
+ if (!showLoginOnOtherPlaces) {
314
+ showLoginOnOtherPlaces = true
315
+ MessageBox.confirm('账户已在别处登录, 请重新登录~', '提示', {
316
+ confirmButtonText: '确定',
317
+ type: 'warning',
318
+ showCancelButton: false,
319
+ callback() {
320
+ // 删除token
321
+ token.remove()
322
+ router.push({
323
+ name: 'login',
324
+ query: {
325
+ redirect
326
+ }
327
+ })
328
+ showLoginOnOtherPlaces = false
329
+ }
330
+ })
331
+ }
332
+ break
333
+ default:
334
+ console.error(error.response.data.msg)
335
+ Message.error({
336
+ message: '系统异常,请联系管理员~',
337
+ duration: messageDuration
338
+ })
339
+ break
340
+ }
341
+ } else {
342
+ if (currentRoute.name === 'login') {
343
+ Message.error({
344
+ message: '无法连接网络~',
345
+ duration: messageDuration
346
+ })
347
+ } else {
348
+ token.remove()
349
+ router.push({ name: 'login', query: { redirect } })
350
+ }
351
+ }
352
+ return Promise.reject(error)
353
+ }
354
+ )
355
+ }