vue2-client 1.2.25 → 1.2.28
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/CHANGELOG.md +56 -48
- package/package.json +1 -1
- package/src/base-client/components/common/XAddNativeForm/XAddNativeForm.vue +315 -0
- package/src/base-client/components/common/XAddNativeForm/index.js +3 -0
- package/src/base-client/components/common/XAddNativeForm/index.md +56 -0
- package/src/utils/request.js +197 -197
- package/src/utils/routerUtil.js +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,48 +1,56 @@
|
|
|
1
|
-
# Change Log
|
|
2
|
-
> 所有关于本项目的变化都在该文档里。
|
|
3
|
-
|
|
4
|
-
**##1.2.
|
|
5
|
-
- 功能修改:
|
|
6
|
-
- [
|
|
7
|
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
- [
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
- [
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
- [
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
-
|
|
30
|
-
- [
|
|
31
|
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
- [
|
|
35
|
-
|
|
36
|
-
**##1.2.
|
|
37
|
-
-
|
|
38
|
-
- [
|
|
39
|
-
- [
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
-
|
|
43
|
-
|
|
44
|
-
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
-
|
|
48
|
-
|
|
1
|
+
# Change Log
|
|
2
|
+
> 所有关于本项目的变化都在该文档里。
|
|
3
|
+
|
|
4
|
+
**##1.2.28 -2022-03-29 @朱子峰**
|
|
5
|
+
- 功能修改:
|
|
6
|
+
- [Cookie]:去除自定义Cookie
|
|
7
|
+
|
|
8
|
+
**##1.2.27 -2022-03-29 @朱子峰**
|
|
9
|
+
- 功能新增:
|
|
10
|
+
- [XAddNativeForm]:将XAddForm从模态框中抽取,用于页面直接展示Form
|
|
11
|
+
|
|
12
|
+
**##1.2.25 -2022-03-26 @江超**
|
|
13
|
+
- 功能修改:
|
|
14
|
+
- [查询配置生成]:表单[新增/修改场景]增加[version(版本号)]类型
|
|
15
|
+
- [api.js]:移除[跨域代理前缀]
|
|
16
|
+
- 问题修复:
|
|
17
|
+
- [查询配置生成]:修复修改已有查询配置时,部分数据显示状态不一致的问题
|
|
18
|
+
- [设备详情页]:修复设备抄表记录,异常记录查询报错的问题
|
|
19
|
+
- [XFormItem]:修复非懒加载搜索的下拉框显示问题
|
|
20
|
+
|
|
21
|
+
**##1.2.20 - 1.2.24 -2022-03-25 @朱子峰**
|
|
22
|
+
- 功能修改:
|
|
23
|
+
- [工单关闭/开始处理]:工单关闭和开始处理时,不由id来进行判断,改由姓名进行判断是否为同一个人
|
|
24
|
+
|
|
25
|
+
**##1.2.17 - 1.2.19 -2022-03-25 @朱子峰**
|
|
26
|
+
- 问题修复:
|
|
27
|
+
- [钉钉消息推送]:将类别字段从int修改为String,直接传字典中的值
|
|
28
|
+
- 功能修改:
|
|
29
|
+
- [问题描述]:如果用户没有填写描述,新增默认值:“该用户没有填写描述信息”
|
|
30
|
+
- [问题描述]:展示问题描述时,按时间倒序展示,最新的信息显示在最上面
|
|
31
|
+
|
|
32
|
+
**##1.2.16 -2022-03-25 @张振宇**
|
|
33
|
+
- 功能修改:
|
|
34
|
+
- [查询配置生成]:逻辑修改,取消选择组和顺序,用户新增数组字段时需要选择是否为根节点,根节点index为1,不是根节点得数据字段index默认为父节点index+1
|
|
35
|
+
|
|
36
|
+
**##1.2.9 - 1.2.15 -2022-03-24 @江超**
|
|
37
|
+
- 功能新增:
|
|
38
|
+
- [查询配置生成]:下拉框表单选择业务逻辑作为数据源时,可以选择数据源加载方式
|
|
39
|
+
- [XFormItem]:当数据源加载方式为懒加载搜索时,将渲染一个可以根据关键词实时查询的选择框
|
|
40
|
+
- 问题修复:
|
|
41
|
+
- [查询配置生成]:修复修改已有查询配置时,显示状态不一致的问题
|
|
42
|
+
- [指令详情页]:修复操作记录查询报错的问题
|
|
43
|
+
|
|
44
|
+
**##1.2.8 -2022-03-24 @江超**
|
|
45
|
+
- 问题修复:
|
|
46
|
+
- [登录页面]:修复登录后欢迎提示出现undefined的问题
|
|
47
|
+
- [查询配置生成]:修复修改表单查询方式下拉框报错的问题
|
|
48
|
+
|
|
49
|
+
**##1.2.7 -2022-03-24 @江超**
|
|
50
|
+
- 功能新增:
|
|
51
|
+
- [系统设置]:新增 [工单提交] 功能(submitTicket),用户在操作业务时如发现系统异常,可使用该功能反馈问题
|
|
52
|
+
- [登录页面]:登陆人部门为 [用户工单登记] 时会直接跳转到[工单提交]页面(在基于新架构的营收全面使用时,会取消该限制,并将[工单提交]作为常驻功能)
|
|
53
|
+
|
|
54
|
+
**##1.0.0 - 1.2.6 -2022-03-23 @陈栋扬**
|
|
55
|
+
- 初始化:
|
|
56
|
+
- 公共组件和配置抽取完成
|
package/package.json
CHANGED
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="table-page-search-wrapper">
|
|
3
|
+
<a-form-model
|
|
4
|
+
v-if="loaded"
|
|
5
|
+
ref="selectForm"
|
|
6
|
+
:model="form"
|
|
7
|
+
:rules="rules">
|
|
8
|
+
<a-row :gutter="16">
|
|
9
|
+
<x-form-item
|
|
10
|
+
v-for="(item, index) in realJsonData"
|
|
11
|
+
mode="新增/修改"
|
|
12
|
+
:attr="item"
|
|
13
|
+
:form="form"
|
|
14
|
+
:key="index"
|
|
15
|
+
:disabled="itemDisabled(item)"
|
|
16
|
+
:xl="12"
|
|
17
|
+
:xxl="8"
|
|
18
|
+
/>
|
|
19
|
+
<div v-for="group in realJsonSelectsData" :key="group[0].group">
|
|
20
|
+
<x-form-col v-for="groupItem in group" :key="groupItem.group + groupItem.groupIndex" :xl="12" :xxl="8">
|
|
21
|
+
<a-form-model-item :label="groupItem.name" :disabled="itemDisabled(groupItem)">
|
|
22
|
+
<a-select v-model="form[groupItem.model]" :disabled="itemDisabledPlus(groupItem.group,groupItem.groupIndex)" :allowClear="true" @change="selectsItemCheck(groupItem.group,groupItem.groupIndex,form[groupItem.model],group)" placeholder="请选择">
|
|
23
|
+
<template v-for="option in SelectsArray[groupItem.group][groupItem.groupIndex]">
|
|
24
|
+
<a-select-option :key="option.label" :value="option.value">
|
|
25
|
+
{{ option.label }}
|
|
26
|
+
</a-select-option>
|
|
27
|
+
</template>
|
|
28
|
+
</a-select>
|
|
29
|
+
</a-form-model-item>
|
|
30
|
+
</x-form-col>
|
|
31
|
+
</div>
|
|
32
|
+
</a-row>
|
|
33
|
+
</a-form-model>
|
|
34
|
+
</div>
|
|
35
|
+
</template>
|
|
36
|
+
<script>
|
|
37
|
+
import XFormItem from '@vue2-client/base-client/components/common/XForm/XFormItem'
|
|
38
|
+
import { formatDate } from '@vue2-client/utils/util'
|
|
39
|
+
import { mapState } from 'vuex'
|
|
40
|
+
import { post } from '@vue2-client/services/api/restTools'
|
|
41
|
+
|
|
42
|
+
export default {
|
|
43
|
+
name: 'XAddNativeForm',
|
|
44
|
+
components: {
|
|
45
|
+
XFormItem
|
|
46
|
+
},
|
|
47
|
+
data () {
|
|
48
|
+
return {
|
|
49
|
+
// 内容加载是否完成
|
|
50
|
+
loaded: false,
|
|
51
|
+
// 表单Model
|
|
52
|
+
form: undefined,
|
|
53
|
+
// 多层下拉框组 数据储存
|
|
54
|
+
SelectsArray: {},
|
|
55
|
+
// 多层下拉框组 各组数量
|
|
56
|
+
SelectsNumber: {},
|
|
57
|
+
// 校验
|
|
58
|
+
rules: {},
|
|
59
|
+
// 图标样式
|
|
60
|
+
iconStyle: {
|
|
61
|
+
position: 'relative',
|
|
62
|
+
top: '1px'
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
computed: {
|
|
67
|
+
// 过滤出用于新增/修改场景的表单项
|
|
68
|
+
realJsonData: function () {
|
|
69
|
+
return this.jsonData.filter(function (item) {
|
|
70
|
+
return item.addOrEdit && item.addOrEdit !== 'no' && item.addOrEdit !== 'silenceAdd' && !item.group
|
|
71
|
+
})
|
|
72
|
+
},
|
|
73
|
+
// 过滤出多个下拉框分组级联得数据
|
|
74
|
+
realJsonSelectsData: function () {
|
|
75
|
+
const Selectsata = this.jsonData.filter(item => !item.isOnlyAddOrEdit && item.group)
|
|
76
|
+
const groupName = [...new Set(Selectsata.map(item => item.group))]
|
|
77
|
+
// 初始化数据组
|
|
78
|
+
groupName.forEach(item => {
|
|
79
|
+
this.SelectsArray[item] = []
|
|
80
|
+
})
|
|
81
|
+
return groupName.map(groupName => {
|
|
82
|
+
const SelectsItem = Selectsata.filter(item => {
|
|
83
|
+
if (item.groupIndex === 1) {
|
|
84
|
+
if (item.keyName.substring(0, 6) === 'logic@') {
|
|
85
|
+
// 请求logic
|
|
86
|
+
post('/webmeterapi/' + item.keyName.substring(6), {}).then(res => {
|
|
87
|
+
this.SelectsArray[item.group][item.groupIndex] = res
|
|
88
|
+
})
|
|
89
|
+
} else {
|
|
90
|
+
this.SelectsArray[item.group][item.groupIndex] = JSON.parse(item.keyName)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return item.group === groupName
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
this.SelectsNumber[groupName] = SelectsItem.length ? SelectsItem.length : 0
|
|
97
|
+
return SelectsItem
|
|
98
|
+
})
|
|
99
|
+
},
|
|
100
|
+
// 过滤出用于静默新增场景的表单项
|
|
101
|
+
silenceAddJsonData: function () {
|
|
102
|
+
return this.jsonData.filter(function (item) {
|
|
103
|
+
return item.addOrEdit === 'silenceAdd'
|
|
104
|
+
})
|
|
105
|
+
},
|
|
106
|
+
// 过滤出版本号表单项
|
|
107
|
+
versionJsonData: function () {
|
|
108
|
+
return this.jsonData.filter(function (item) {
|
|
109
|
+
return item.addOrEdit === 'version'
|
|
110
|
+
})
|
|
111
|
+
},
|
|
112
|
+
...mapState('account', { currUser: 'user' })
|
|
113
|
+
},
|
|
114
|
+
props: {
|
|
115
|
+
jsonData: {
|
|
116
|
+
type: Array,
|
|
117
|
+
default: () => {
|
|
118
|
+
return []
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
// 业务类型
|
|
122
|
+
businessType: {
|
|
123
|
+
type: String,
|
|
124
|
+
default: ''
|
|
125
|
+
},
|
|
126
|
+
// 修改操作前查询出的业务数据
|
|
127
|
+
modifyModelData: {
|
|
128
|
+
type: Object,
|
|
129
|
+
default: () => {
|
|
130
|
+
return {}
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
// 新增或修改业务是否执行中
|
|
134
|
+
loading: {
|
|
135
|
+
type: Boolean,
|
|
136
|
+
default: () => {
|
|
137
|
+
return false
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
// 固定新增表单
|
|
141
|
+
fixedAddForm: {
|
|
142
|
+
type: Object,
|
|
143
|
+
default: () => {
|
|
144
|
+
return {}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
watch: {
|
|
149
|
+
visible (rel) {
|
|
150
|
+
if (rel) {
|
|
151
|
+
this.formItemLoad()
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
mounted () {
|
|
156
|
+
this.formItemLoad()
|
|
157
|
+
},
|
|
158
|
+
methods: {
|
|
159
|
+
selectsItemCheck (groupName, index, value, group) {
|
|
160
|
+
const tem = { }
|
|
161
|
+
// 获取当前下拉框子下拉框的数据
|
|
162
|
+
this.SelectsArray[groupName][index + 1] = this.SelectsArray[groupName][index].filter(item => item.value === value)[0].children
|
|
163
|
+
// 清空子下拉框的子们的数据
|
|
164
|
+
for (let i = index; i < this.SelectsNumber[groupName]; i++) {
|
|
165
|
+
tem[group[i].model] = undefined
|
|
166
|
+
}
|
|
167
|
+
this.form = Object.assign({}, this.form, tem)
|
|
168
|
+
// 清空子下拉框的子们的数据源
|
|
169
|
+
for (let i = index + 2; i <= this.SelectsNumber[groupName]; i++) {
|
|
170
|
+
this.SelectsArray[groupName][i] = []
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
formItemLoad () {
|
|
174
|
+
const formData = Object.assign({}, this.fixedAddForm)
|
|
175
|
+
for (let i = 0; i < this.realJsonData.length; i++) {
|
|
176
|
+
const item = this.realJsonData[i]
|
|
177
|
+
formData[item.model] = undefined
|
|
178
|
+
// 处理表单校验情况
|
|
179
|
+
if (item.rule) {
|
|
180
|
+
this.rules[item.model] = []
|
|
181
|
+
const required = item.rule.required ? item.rule.required === true || item.rule.required === 'true' : false
|
|
182
|
+
let trigger
|
|
183
|
+
let message
|
|
184
|
+
if (required) {
|
|
185
|
+
switch (item.type) {
|
|
186
|
+
case 'select':
|
|
187
|
+
message = '请选择' + item.name
|
|
188
|
+
trigger = 'change'
|
|
189
|
+
break
|
|
190
|
+
default:
|
|
191
|
+
message = '请输入' + item.name
|
|
192
|
+
trigger = 'blur'
|
|
193
|
+
}
|
|
194
|
+
this.rules[item.model].push({
|
|
195
|
+
required: true,
|
|
196
|
+
message: message,
|
|
197
|
+
trigger: trigger
|
|
198
|
+
})
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
switch (item.rule.type) {
|
|
202
|
+
case 'number':
|
|
203
|
+
case 'integer':
|
|
204
|
+
case 'float':
|
|
205
|
+
let defaultValue
|
|
206
|
+
let message
|
|
207
|
+
switch (item.rule.type) {
|
|
208
|
+
case 'number':
|
|
209
|
+
message = '数字'
|
|
210
|
+
defaultValue = 0
|
|
211
|
+
break
|
|
212
|
+
case 'integer':
|
|
213
|
+
message = '整数'
|
|
214
|
+
defaultValue = 0
|
|
215
|
+
break
|
|
216
|
+
case 'float':
|
|
217
|
+
message = '小数'
|
|
218
|
+
defaultValue = 0.0
|
|
219
|
+
break
|
|
220
|
+
}
|
|
221
|
+
this.rules[item.model].push({
|
|
222
|
+
type: item.rule.type,
|
|
223
|
+
message: item.name + '必须为' + message,
|
|
224
|
+
transform: (value) => {
|
|
225
|
+
if (value && value.length !== 0) {
|
|
226
|
+
return Number(value)
|
|
227
|
+
} else {
|
|
228
|
+
return defaultValue
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
trigger: 'blur'
|
|
232
|
+
})
|
|
233
|
+
break
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
this.form = formData
|
|
238
|
+
if (Object.keys(this.modifyModelData).length > 0) {
|
|
239
|
+
this.getModifyModelData()
|
|
240
|
+
}
|
|
241
|
+
this.loaded = true
|
|
242
|
+
},
|
|
243
|
+
itemDisabled (value) {
|
|
244
|
+
return (this.businessType === '新增' && value.addOrEdit === 'edit') ||
|
|
245
|
+
(this.businessType === '修改' && value.addOrEdit === 'add')
|
|
246
|
+
},
|
|
247
|
+
itemDisabledPlus (group, index) {
|
|
248
|
+
return (!this.SelectsArray[group][index]) || (this.SelectsArray[group][index] && this.SelectsArray[group][index].length === 0)
|
|
249
|
+
},
|
|
250
|
+
resetForm () {
|
|
251
|
+
this.$refs.selectForm.resetFields()
|
|
252
|
+
},
|
|
253
|
+
async onSubmit () {
|
|
254
|
+
this.$refs.selectForm.validate(async valid => {
|
|
255
|
+
for (const key of Object.keys(this.form)) {
|
|
256
|
+
if (this.form[key] === null || this.form[key] === '') {
|
|
257
|
+
this.form[key] = undefined
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
const requestParameters = Object.assign({}, this.form)
|
|
261
|
+
// 追加静默新增字段
|
|
262
|
+
if (this.businessType === '新增') {
|
|
263
|
+
for (const item of this.silenceAddJsonData) {
|
|
264
|
+
switch (item.silencePurpose) {
|
|
265
|
+
case 'createTime':
|
|
266
|
+
requestParameters[item.model] = formatDate('now')
|
|
267
|
+
break
|
|
268
|
+
case 'operator':
|
|
269
|
+
requestParameters[item.model] = this.currUser.name
|
|
270
|
+
break
|
|
271
|
+
case 'orgId':
|
|
272
|
+
requestParameters[item.model] = this.currUser.orgid
|
|
273
|
+
break
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
// 通过请求追加静默新增:自定义字段
|
|
277
|
+
for (const item of this.silenceAddJsonData.filter((item) => item.silencePurpose === 'customize')) {
|
|
278
|
+
requestParameters[item.model] = await this.getSilenceSource(item.silenceSource, requestParameters)
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
const data = {
|
|
282
|
+
valid: valid,
|
|
283
|
+
form: requestParameters
|
|
284
|
+
}
|
|
285
|
+
this.$emit('onSubmit', data)
|
|
286
|
+
})
|
|
287
|
+
},
|
|
288
|
+
async getSilenceSource (silenceSource, requestParameters) {
|
|
289
|
+
const result = await post('/webmeterapi/' + silenceSource, requestParameters)
|
|
290
|
+
return result
|
|
291
|
+
},
|
|
292
|
+
getModifyModelData () {
|
|
293
|
+
for (let i = 0; i < this.realJsonData.length; i++) {
|
|
294
|
+
const item = this.realJsonData[i]
|
|
295
|
+
if (this.modifyModelData[item.model] || this.modifyModelData[item.model] === 0) {
|
|
296
|
+
this.form[item.model] = this.modifyModelData[item.model] + ''
|
|
297
|
+
} else {
|
|
298
|
+
this.form[item.model] = undefined
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
// 追加版本号信息
|
|
302
|
+
for (const item of this.versionJsonData) {
|
|
303
|
+
if (!this.modifyModelData[item.model]) {
|
|
304
|
+
this.form[item.model] = 0
|
|
305
|
+
} else {
|
|
306
|
+
this.form[item.model] = this.modifyModelData[item.model] + ''
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
},
|
|
310
|
+
onClose () {
|
|
311
|
+
this.$emit('update:visible', false)
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
</script>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# XAddNativeForm
|
|
2
|
+
|
|
3
|
+
动态新增/修改表单控件,根据JSON配置生成一个完整的可供新增/修改数据的动态表单
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## 何时使用
|
|
7
|
+
|
|
8
|
+
当需要一个可供新增/修改数据的动态生成的表单时
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
引用方式:
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
import XAddNativeForm from '@vue2-client/base-client/components/XAddNativeForm/XAddNativeForm'
|
|
15
|
+
|
|
16
|
+
export default {
|
|
17
|
+
components: {
|
|
18
|
+
XAddNativeForm
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## 代码演示
|
|
26
|
+
|
|
27
|
+
```html
|
|
28
|
+
<x-add-form
|
|
29
|
+
:business-type="businessType"
|
|
30
|
+
:json-data="formItems"
|
|
31
|
+
:modify-model-data="modifyModelData"
|
|
32
|
+
:loading="loading"
|
|
33
|
+
@onSubmit="onSubmit">
|
|
34
|
+
</x-add-form>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## API
|
|
38
|
+
|
|
39
|
+
| 参数 | 说明 | 类型 | 默认值 |
|
|
40
|
+
|-----------------|--------------------------|---------|-------|
|
|
41
|
+
| businessType | 业务类型 | String | '' |
|
|
42
|
+
| jsonData | JSON配置,根据[工具>查询配置生成]功能生成 | Object | {} |
|
|
43
|
+
| modifyModelData | 修改操作前查询出的业务数据 | Object | {} |
|
|
44
|
+
| loading | 新增或修改业务是否执行中 | Boolean | false |
|
|
45
|
+
| fixedAddForm | 固定新增表单,会和新增表单合并 | Object | {} |
|
|
46
|
+
| @onSubmit | 表单的提交事件 | event | - |
|
|
47
|
+
|
|
48
|
+
## 例子1
|
|
49
|
+
----
|
|
50
|
+
参考XFormTable组件
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
注意事项
|
|
54
|
+
----
|
|
55
|
+
|
|
56
|
+
> 本组件已经实现了自适应布局,在不同分辨率下的设备均可得到基本理想的展示效果
|
package/src/utils/request.js
CHANGED
|
@@ -1,197 +1,197 @@
|
|
|
1
|
-
import axios from 'axios'
|
|
2
|
-
import Cookie from 'js-cookie'
|
|
3
|
-
import Vue from 'vue'
|
|
4
|
-
import { ACCESS_TOKEN } from '@vue2-client/store/mutation-types'
|
|
5
|
-
import notification from 'ant-design-vue/es/notification'
|
|
6
|
-
|
|
7
|
-
// 跨域认证信息 header 名
|
|
8
|
-
const xsrfHeaderName = 'Authorization'
|
|
9
|
-
|
|
10
|
-
axios.defaults.timeout = 5000
|
|
11
|
-
axios.defaults.withCredentials = true
|
|
12
|
-
axios.defaults.xsrfHeaderName = xsrfHeaderName
|
|
13
|
-
axios.defaults.xsrfCookieName = xsrfHeaderName
|
|
14
|
-
|
|
15
|
-
// 认证类型
|
|
16
|
-
const AUTH_TYPE = {
|
|
17
|
-
BEARER: 'Bearer',
|
|
18
|
-
BASIC: 'basic',
|
|
19
|
-
AUTH1: 'auth1',
|
|
20
|
-
AUTH2: 'auth2'
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// http method
|
|
24
|
-
const METHOD = {
|
|
25
|
-
GET: 'get',
|
|
26
|
-
POST: 'post'
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* axios请求
|
|
31
|
-
* @param url 请求地址
|
|
32
|
-
* @param method {METHOD} http method
|
|
33
|
-
* @param params 请求参数
|
|
34
|
-
* @returns {Promise<AxiosResponse<T>>}
|
|
35
|
-
*/
|
|
36
|
-
async function request (url, method, params, config) {
|
|
37
|
-
switch (method) {
|
|
38
|
-
case METHOD.GET:
|
|
39
|
-
return axios.get(url, { params, ...config })
|
|
40
|
-
case METHOD.POST:
|
|
41
|
-
return axios.post(url, params, config)
|
|
42
|
-
default:
|
|
43
|
-
return axios.get(url, { params, ...config })
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* 设置认证信息
|
|
49
|
-
* @param auth {Object}
|
|
50
|
-
* @param authType {AUTH_TYPE} 认证类型,默认:{AUTH_TYPE.BEARER}
|
|
51
|
-
*/
|
|
52
|
-
function setAuthorization (auth, authType = AUTH_TYPE.BEARER) {
|
|
53
|
-
switch (authType) {
|
|
54
|
-
case AUTH_TYPE.BEARER:
|
|
55
|
-
Cookie.set(xsrfHeaderName, 'Bearer ' + auth.token, { expires: auth.expireAt })
|
|
56
|
-
break
|
|
57
|
-
case AUTH_TYPE.BASIC:
|
|
58
|
-
case AUTH_TYPE.AUTH1:
|
|
59
|
-
case AUTH_TYPE.AUTH2:
|
|
60
|
-
default:
|
|
61
|
-
break
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* 移出认证信息
|
|
67
|
-
* @param authType {AUTH_TYPE} 认证类型
|
|
68
|
-
*/
|
|
69
|
-
function removeAuthorization (authType = AUTH_TYPE.BEARER) {
|
|
70
|
-
switch (authType) {
|
|
71
|
-
case AUTH_TYPE.BEARER:
|
|
72
|
-
Cookie.remove(xsrfHeaderName)
|
|
73
|
-
break
|
|
74
|
-
case AUTH_TYPE.BASIC:
|
|
75
|
-
case AUTH_TYPE.AUTH1:
|
|
76
|
-
case AUTH_TYPE.AUTH2:
|
|
77
|
-
default:
|
|
78
|
-
break
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* 检查认证信息
|
|
84
|
-
* @param authType
|
|
85
|
-
* @returns {boolean}
|
|
86
|
-
*/
|
|
87
|
-
function checkAuthorization (authType = AUTH_TYPE.BEARER) {
|
|
88
|
-
switch (authType) {
|
|
89
|
-
case AUTH_TYPE.BEARER:
|
|
90
|
-
if (Cookie.get(xsrfHeaderName)) {
|
|
91
|
-
return true
|
|
92
|
-
}
|
|
93
|
-
break
|
|
94
|
-
case AUTH_TYPE.BASIC:
|
|
95
|
-
case AUTH_TYPE.AUTH1:
|
|
96
|
-
case AUTH_TYPE.AUTH2:
|
|
97
|
-
default:
|
|
98
|
-
break
|
|
99
|
-
}
|
|
100
|
-
return false
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* 加载 axios 拦截器
|
|
105
|
-
* @param interceptors
|
|
106
|
-
* @param options
|
|
107
|
-
*/
|
|
108
|
-
function loadInterceptors () {
|
|
109
|
-
// 加载请求拦截器
|
|
110
|
-
axios.interceptors.request.use(config => {
|
|
111
|
-
const token = localStorage.getItem(ACCESS_TOKEN)
|
|
112
|
-
// 如果 token 存在
|
|
113
|
-
// 让每个请求携带自定义 token 请根据实际情况自行修改
|
|
114
|
-
if (token) {
|
|
115
|
-
config.headers['Access-Token'] = token
|
|
116
|
-
}
|
|
117
|
-
if (!config.headers['Content-Type']) {
|
|
118
|
-
config.headers['Content-Type'] = 'application/json;charset=UTF-8'
|
|
119
|
-
}
|
|
120
|
-
return config
|
|
121
|
-
}, errorHandler)
|
|
122
|
-
// 加载响应拦截器
|
|
123
|
-
axios.interceptors.response.use((response) => {
|
|
124
|
-
return response.data
|
|
125
|
-
}, errorHandler)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// 异常拦截处理器
|
|
129
|
-
const errorHandler = (error) => {
|
|
130
|
-
if (error.response) {
|
|
131
|
-
const data = error.response.data
|
|
132
|
-
// 从 localstorage 获取 token
|
|
133
|
-
const token = localStorage.getItem(ACCESS_TOKEN)
|
|
134
|
-
if (error.response.status === 403) {
|
|
135
|
-
notification.error({
|
|
136
|
-
message: '禁止访问',
|
|
137
|
-
description: data
|
|
138
|
-
})
|
|
139
|
-
} else if (error.response.status === 401 && !(data.result && data.result.isLogin)) {
|
|
140
|
-
notification.error({
|
|
141
|
-
message: '鉴权失败',
|
|
142
|
-
description: data
|
|
143
|
-
})
|
|
144
|
-
if (token) {
|
|
145
|
-
Vue.$store.dispatch('Logout').then(() => {
|
|
146
|
-
setTimeout(() => {
|
|
147
|
-
window.location.reload()
|
|
148
|
-
}, 1500)
|
|
149
|
-
})
|
|
150
|
-
}
|
|
151
|
-
} else if (error.response.status === 500) {
|
|
152
|
-
notification.error({
|
|
153
|
-
message: '系统异常',
|
|
154
|
-
description: data
|
|
155
|
-
})
|
|
156
|
-
} else {
|
|
157
|
-
notification.error({
|
|
158
|
-
message: '数据异常',
|
|
159
|
-
description: data
|
|
160
|
-
})
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
return Promise.reject(error)
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* 解析 url 中的参数
|
|
168
|
-
* @param url
|
|
169
|
-
* @returns {Object}
|
|
170
|
-
*/
|
|
171
|
-
function parseUrlParams (url) {
|
|
172
|
-
const params = {}
|
|
173
|
-
if (!url || url === '' || typeof url !== 'string') {
|
|
174
|
-
return params
|
|
175
|
-
}
|
|
176
|
-
const paramsStr = url.split('?')[1]
|
|
177
|
-
if (!paramsStr) {
|
|
178
|
-
return params
|
|
179
|
-
}
|
|
180
|
-
const paramsArr = paramsStr.replace(/&|=/g, ' ').split(' ')
|
|
181
|
-
for (let i = 0; i < paramsArr.length / 2; i++) {
|
|
182
|
-
const value = paramsArr[i * 2 + 1]
|
|
183
|
-
params[paramsArr[i * 2]] = value === 'true' ? true : (value === 'false' ? false : value)
|
|
184
|
-
}
|
|
185
|
-
return params
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
export {
|
|
189
|
-
METHOD,
|
|
190
|
-
AUTH_TYPE,
|
|
191
|
-
request,
|
|
192
|
-
setAuthorization,
|
|
193
|
-
removeAuthorization,
|
|
194
|
-
checkAuthorization,
|
|
195
|
-
loadInterceptors,
|
|
196
|
-
parseUrlParams
|
|
197
|
-
}
|
|
1
|
+
import axios from 'axios'
|
|
2
|
+
import Cookie from 'js-cookie'
|
|
3
|
+
import Vue from 'vue'
|
|
4
|
+
import { ACCESS_TOKEN } from '@vue2-client/store/mutation-types'
|
|
5
|
+
import notification from 'ant-design-vue/es/notification'
|
|
6
|
+
|
|
7
|
+
// 跨域认证信息 header 名
|
|
8
|
+
const xsrfHeaderName = 'Authorization'
|
|
9
|
+
|
|
10
|
+
axios.defaults.timeout = 5000
|
|
11
|
+
axios.defaults.withCredentials = true
|
|
12
|
+
axios.defaults.xsrfHeaderName = xsrfHeaderName
|
|
13
|
+
axios.defaults.xsrfCookieName = xsrfHeaderName
|
|
14
|
+
|
|
15
|
+
// 认证类型
|
|
16
|
+
const AUTH_TYPE = {
|
|
17
|
+
BEARER: 'Bearer',
|
|
18
|
+
BASIC: 'basic',
|
|
19
|
+
AUTH1: 'auth1',
|
|
20
|
+
AUTH2: 'auth2'
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// http method
|
|
24
|
+
const METHOD = {
|
|
25
|
+
GET: 'get',
|
|
26
|
+
POST: 'post'
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* axios请求
|
|
31
|
+
* @param url 请求地址
|
|
32
|
+
* @param method {METHOD} http method
|
|
33
|
+
* @param params 请求参数
|
|
34
|
+
* @returns {Promise<AxiosResponse<T>>}
|
|
35
|
+
*/
|
|
36
|
+
async function request (url, method, params, config) {
|
|
37
|
+
switch (method) {
|
|
38
|
+
case METHOD.GET:
|
|
39
|
+
return axios.get(url, { params, ...config })
|
|
40
|
+
case METHOD.POST:
|
|
41
|
+
return axios.post(url, params, config)
|
|
42
|
+
default:
|
|
43
|
+
return axios.get(url, { params, ...config })
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* 设置认证信息
|
|
49
|
+
* @param auth {Object}
|
|
50
|
+
* @param authType {AUTH_TYPE} 认证类型,默认:{AUTH_TYPE.BEARER}
|
|
51
|
+
*/
|
|
52
|
+
function setAuthorization (auth, authType = AUTH_TYPE.BEARER) {
|
|
53
|
+
switch (authType) {
|
|
54
|
+
case AUTH_TYPE.BEARER:
|
|
55
|
+
Cookie.set(xsrfHeaderName, 'Bearer ' + auth.token, { expires: auth.expireAt })
|
|
56
|
+
break
|
|
57
|
+
case AUTH_TYPE.BASIC:
|
|
58
|
+
case AUTH_TYPE.AUTH1:
|
|
59
|
+
case AUTH_TYPE.AUTH2:
|
|
60
|
+
default:
|
|
61
|
+
break
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* 移出认证信息
|
|
67
|
+
* @param authType {AUTH_TYPE} 认证类型
|
|
68
|
+
*/
|
|
69
|
+
function removeAuthorization (authType = AUTH_TYPE.BEARER) {
|
|
70
|
+
switch (authType) {
|
|
71
|
+
case AUTH_TYPE.BEARER:
|
|
72
|
+
Cookie.remove(xsrfHeaderName)
|
|
73
|
+
break
|
|
74
|
+
case AUTH_TYPE.BASIC:
|
|
75
|
+
case AUTH_TYPE.AUTH1:
|
|
76
|
+
case AUTH_TYPE.AUTH2:
|
|
77
|
+
default:
|
|
78
|
+
break
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 检查认证信息
|
|
84
|
+
* @param authType
|
|
85
|
+
* @returns {boolean}
|
|
86
|
+
*/
|
|
87
|
+
function checkAuthorization (authType = AUTH_TYPE.BEARER) {
|
|
88
|
+
switch (authType) {
|
|
89
|
+
case AUTH_TYPE.BEARER:
|
|
90
|
+
if (Cookie.get(xsrfHeaderName)) {
|
|
91
|
+
return true
|
|
92
|
+
}
|
|
93
|
+
break
|
|
94
|
+
case AUTH_TYPE.BASIC:
|
|
95
|
+
case AUTH_TYPE.AUTH1:
|
|
96
|
+
case AUTH_TYPE.AUTH2:
|
|
97
|
+
default:
|
|
98
|
+
break
|
|
99
|
+
}
|
|
100
|
+
return false
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* 加载 axios 拦截器
|
|
105
|
+
* @param interceptors
|
|
106
|
+
* @param options
|
|
107
|
+
*/
|
|
108
|
+
function loadInterceptors () {
|
|
109
|
+
// 加载请求拦截器
|
|
110
|
+
axios.interceptors.request.use(config => {
|
|
111
|
+
const token = localStorage.getItem(ACCESS_TOKEN)
|
|
112
|
+
// 如果 token 存在
|
|
113
|
+
// 让每个请求携带自定义 token 请根据实际情况自行修改
|
|
114
|
+
if (token) {
|
|
115
|
+
config.headers['Access-Token'] = token
|
|
116
|
+
}
|
|
117
|
+
if (!config.headers['Content-Type']) {
|
|
118
|
+
config.headers['Content-Type'] = 'application/json;charset=UTF-8'
|
|
119
|
+
}
|
|
120
|
+
return config
|
|
121
|
+
}, errorHandler)
|
|
122
|
+
// 加载响应拦截器
|
|
123
|
+
axios.interceptors.response.use((response) => {
|
|
124
|
+
return response.data
|
|
125
|
+
}, errorHandler)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// 异常拦截处理器
|
|
129
|
+
const errorHandler = (error) => {
|
|
130
|
+
if (error.response) {
|
|
131
|
+
const data = error.response.data
|
|
132
|
+
// 从 localstorage 获取 token
|
|
133
|
+
const token = localStorage.getItem(ACCESS_TOKEN)
|
|
134
|
+
if (error.response.status === 403) {
|
|
135
|
+
notification.error({
|
|
136
|
+
message: '禁止访问',
|
|
137
|
+
description: data
|
|
138
|
+
})
|
|
139
|
+
} else if (error.response.status === 401 && !(data.result && data.result.isLogin)) {
|
|
140
|
+
notification.error({
|
|
141
|
+
message: '鉴权失败',
|
|
142
|
+
description: data
|
|
143
|
+
})
|
|
144
|
+
if (token) {
|
|
145
|
+
Vue.$store.dispatch('Logout').then(() => {
|
|
146
|
+
setTimeout(() => {
|
|
147
|
+
window.location.reload()
|
|
148
|
+
}, 1500)
|
|
149
|
+
})
|
|
150
|
+
}
|
|
151
|
+
} else if (error.response.status === 500) {
|
|
152
|
+
notification.error({
|
|
153
|
+
message: '系统异常',
|
|
154
|
+
description: data
|
|
155
|
+
})
|
|
156
|
+
} else {
|
|
157
|
+
notification.error({
|
|
158
|
+
message: '数据异常',
|
|
159
|
+
description: data
|
|
160
|
+
})
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return Promise.reject(error)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* 解析 url 中的参数
|
|
168
|
+
* @param url
|
|
169
|
+
* @returns {Object}
|
|
170
|
+
*/
|
|
171
|
+
function parseUrlParams (url) {
|
|
172
|
+
const params = {}
|
|
173
|
+
if (!url || url === '' || typeof url !== 'string') {
|
|
174
|
+
return params
|
|
175
|
+
}
|
|
176
|
+
const paramsStr = url.split('?')[1]
|
|
177
|
+
if (!paramsStr) {
|
|
178
|
+
return params
|
|
179
|
+
}
|
|
180
|
+
const paramsArr = paramsStr.replace(/&|=/g, ' ').split(' ')
|
|
181
|
+
for (let i = 0; i < paramsArr.length / 2; i++) {
|
|
182
|
+
const value = paramsArr[i * 2 + 1]
|
|
183
|
+
params[paramsArr[i * 2]] = value === 'true' ? true : (value === 'false' ? false : value)
|
|
184
|
+
}
|
|
185
|
+
return params
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export {
|
|
189
|
+
METHOD,
|
|
190
|
+
AUTH_TYPE,
|
|
191
|
+
request,
|
|
192
|
+
setAuthorization,
|
|
193
|
+
removeAuthorization,
|
|
194
|
+
checkAuthorization,
|
|
195
|
+
loadInterceptors,
|
|
196
|
+
parseUrlParams
|
|
197
|
+
}
|
package/src/utils/routerUtil.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import Vue from 'vue'
|
|
1
2
|
import routerMap from '@vue2-client/router/async/router.map'
|
|
2
3
|
import { mergeI18nFromRoutes } from '@vue2-client/utils/i18n'
|
|
3
4
|
import Router from 'vue-router'
|
|
@@ -135,6 +136,11 @@ function loadRoutes (routesConfig) {
|
|
|
135
136
|
// 应用配置
|
|
136
137
|
const { router, store, i18n } = appOptions
|
|
137
138
|
|
|
139
|
+
// 刷新页面时,有些全局状态丢失,在此处从本地缓存拿出来赋值
|
|
140
|
+
if (JSON.stringify(Vue.$login.f) == '{}') {
|
|
141
|
+
const login = store.getters['account/login']
|
|
142
|
+
Object.assign(Vue.$login, login)
|
|
143
|
+
}
|
|
138
144
|
// 如果 routesConfig 有值,则更新到本地,否则从本地获取
|
|
139
145
|
if (routesConfig) {
|
|
140
146
|
store.commit('account/setRoutesConfig', routesConfig)
|