@netang/quasar 0.0.20 → 0.0.22
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/README.md +2 -3
- package/components/dialog/index.vue +30 -2
- package/components/drawer/index.vue +54 -25
- package/components/empty/index.vue +23 -0
- package/components/field-table/index.vue +85 -115
- package/components/power-page/index.vue +47 -0
- package/components/private/table-visible-columns-button/index.vue +105 -0
- package/components/table/index.vue +31 -85
- package/components/table-column-fixed/index.vue +20 -10
- package/components/table-pagination/index.vue +83 -3
- package/components/table-summary/index.vue +14 -2
- package/components/toolbar/index.vue +44 -311
- package/components/uploader/index.vue +6 -8
- package/components/uploader-query/index.vue +1 -3
- package/package.json +1 -1
- package/store/index.js +14 -0
- package/utils/$form.js +52 -0
- package/utils/{$role.js → $power.js} +313 -106
- package/utils/$table.js +69 -88
- package/utils/$tree.js +56 -32
- package/utils/http.js +5 -5
- package/utils/symbols.js +4 -0
- package/components/layout/index.vue +0 -119
|
@@ -1,10 +1,263 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { provide, inject, ref, computed } from 'vue'
|
|
2
|
+
import { useQuasar } from 'quasar'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { statePower } from '../store'
|
|
5
|
+
import { NPowerKey, NFormKey, NTableKey } from './symbols'
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
|
-
*
|
|
8
|
+
* 创建权限实例
|
|
9
|
+
*/
|
|
10
|
+
function create(params) {
|
|
11
|
+
|
|
12
|
+
// 获取参数
|
|
13
|
+
const o = Object.assign({
|
|
14
|
+
// 路由路径
|
|
15
|
+
path: '',
|
|
16
|
+
// 路由参数
|
|
17
|
+
query: {},
|
|
18
|
+
// 页面加载
|
|
19
|
+
pageLoading: false,
|
|
20
|
+
// 页面状态
|
|
21
|
+
pageStatus: null,
|
|
22
|
+
// 空状态描述
|
|
23
|
+
emptyDescription: '',
|
|
24
|
+
// 是否开启权限
|
|
25
|
+
power: true,
|
|
26
|
+
// 左边侧滑菜单图标
|
|
27
|
+
leftDrawerIcon: 'format_list_bulleted',
|
|
28
|
+
// 右边侧滑菜单图标
|
|
29
|
+
rightDrawerIcon: 'search',
|
|
30
|
+
|
|
31
|
+
// 请求前执行
|
|
32
|
+
requestBefore: null,
|
|
33
|
+
// 请求成功执行
|
|
34
|
+
requestSuccess: null,
|
|
35
|
+
// 请求失败执行
|
|
36
|
+
requestFail: null,
|
|
37
|
+
// 请求后执行
|
|
38
|
+
requestAfter: null,
|
|
39
|
+
}, params)
|
|
40
|
+
|
|
41
|
+
// 获取权限路由
|
|
42
|
+
const $route = utils.isValidString(o.path) ?
|
|
43
|
+
// 如果为自定义路由
|
|
44
|
+
utils.router.resolve({
|
|
45
|
+
path: o.path,
|
|
46
|
+
query: o.query,
|
|
47
|
+
})
|
|
48
|
+
// 否则获取当前路由
|
|
49
|
+
: utils.router.getRoute()
|
|
50
|
+
|
|
51
|
+
// quasar 对象
|
|
52
|
+
const $q = useQuasar()
|
|
53
|
+
|
|
54
|
+
// 表格已选数据
|
|
55
|
+
const tableSelected = ref([])
|
|
56
|
+
|
|
57
|
+
// 是否显示左边侧滑菜单
|
|
58
|
+
const leftDrawerModelValue = ref(null)
|
|
59
|
+
|
|
60
|
+
// 是否显示右边侧滑菜单
|
|
61
|
+
const rightDrawerModelValue = ref(null)
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 检查是否上传中
|
|
65
|
+
*/
|
|
66
|
+
function checkUploading() {
|
|
67
|
+
for (const uploader of data.uploader) {
|
|
68
|
+
if (uploader.checkUploading()) {
|
|
69
|
+
return true
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return false
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const _data = {
|
|
76
|
+
// 表格实例
|
|
77
|
+
$table: null,
|
|
78
|
+
// 表单实例
|
|
79
|
+
$form: null,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// 注入数据
|
|
83
|
+
const data = {
|
|
84
|
+
// 页面加载
|
|
85
|
+
pageLoading: ref(o.pageLoading),
|
|
86
|
+
// 页面状态
|
|
87
|
+
pageStatus: ref(o.pageStatus),
|
|
88
|
+
// 空状态描述
|
|
89
|
+
emptyDescription: ref(o.emptyDescription),
|
|
90
|
+
|
|
91
|
+
// 当前路由全路径
|
|
92
|
+
routeFullPath: $route.fullPath,
|
|
93
|
+
// 当前路由路径
|
|
94
|
+
routePath: $route.path,
|
|
95
|
+
// 当前路由参数
|
|
96
|
+
routeQuery: $route.query,
|
|
97
|
+
// 获取当前路由
|
|
98
|
+
getRoute() {
|
|
99
|
+
return $route
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
// 左边侧滑菜单数据
|
|
103
|
+
leftDrawer: {
|
|
104
|
+
// 图标
|
|
105
|
+
icon: o.leftDrawerIcon,
|
|
106
|
+
// 是否显示
|
|
107
|
+
modelValue: leftDrawerModelValue,
|
|
108
|
+
// 是否显示切换按钮
|
|
109
|
+
showButton() {
|
|
110
|
+
return leftDrawerModelValue.value !== null
|
|
111
|
+
},
|
|
112
|
+
// 切换
|
|
113
|
+
toggle() {
|
|
114
|
+
if (leftDrawerModelValue.value !== null) {
|
|
115
|
+
leftDrawerModelValue.value = ! leftDrawerModelValue.value
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
// 右边侧滑菜单数据
|
|
120
|
+
rightDrawer: {
|
|
121
|
+
// 图标
|
|
122
|
+
icon: o.rightDrawerIcon,
|
|
123
|
+
// 是否显示
|
|
124
|
+
modelValue: rightDrawerModelValue,
|
|
125
|
+
// 是否显示切换按钮
|
|
126
|
+
showButton() {
|
|
127
|
+
return rightDrawerModelValue.value !== null
|
|
128
|
+
},
|
|
129
|
+
// 切换
|
|
130
|
+
toggle() {
|
|
131
|
+
if (rightDrawerModelValue.value !== null) {
|
|
132
|
+
rightDrawerModelValue.value = ! rightDrawerModelValue.value
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
// 表格已选数据
|
|
137
|
+
tableSelected,
|
|
138
|
+
// 上传器
|
|
139
|
+
uploader: [],
|
|
140
|
+
// 检查是否上传中
|
|
141
|
+
checkUploading,
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// 如果是权限页面
|
|
145
|
+
if (o.power) {
|
|
146
|
+
|
|
147
|
+
// 获取当前页面角色权限
|
|
148
|
+
const { status, data: res } = getPageData($route)
|
|
149
|
+
if (! status) {
|
|
150
|
+
o.pageStatus = false
|
|
151
|
+
o.emptyDescription = res.msg
|
|
152
|
+
o.power = false
|
|
153
|
+
|
|
154
|
+
} else {
|
|
155
|
+
// 当前页面权限
|
|
156
|
+
data.powerPage = res.page
|
|
157
|
+
// 当前页面权限按钮
|
|
158
|
+
data.powerBtns = ref(res.btns)
|
|
159
|
+
// 当前页面工具栏权限按钮
|
|
160
|
+
data.toolbarPowerBtns = computed(function() {
|
|
161
|
+
|
|
162
|
+
// 有权限按钮数据
|
|
163
|
+
if (utils.isValidArray(data.powerBtns.value)) {
|
|
164
|
+
|
|
165
|
+
const lists = _.filter(formatBtns(data.powerBtns.value), e => e.type > 2)
|
|
166
|
+
|
|
167
|
+
// 格式化权限按钮列表
|
|
168
|
+
utils.forEach(lists, function(item) {
|
|
169
|
+
|
|
170
|
+
if (! item.hidden) {
|
|
171
|
+
|
|
172
|
+
// 如果是单条数据显示
|
|
173
|
+
const isSingle = item.show === 'single'
|
|
174
|
+
|
|
175
|
+
// 如果是单条 || 多条显示
|
|
176
|
+
if (isSingle || item.show === 'multi') {
|
|
177
|
+
|
|
178
|
+
// 初始为不显示
|
|
179
|
+
item.show = false
|
|
180
|
+
|
|
181
|
+
// 如果有表格选中数据
|
|
182
|
+
if (utils.isValidArray(data.tableSelected.value)) {
|
|
183
|
+
// 如果是单个显示
|
|
184
|
+
if (isSingle) {
|
|
185
|
+
item.show = data.tableSelected.value.length === 1
|
|
186
|
+
|
|
187
|
+
// 否则是多个显示
|
|
188
|
+
} else {
|
|
189
|
+
item.show = data.tableSelected.value.length >= 1
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// 如果是手机模式
|
|
195
|
+
if ($q.platform.is.mobile) {
|
|
196
|
+
item.icon = undefined
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
return lists
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return []
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
// 权限按钮点击
|
|
208
|
+
data.powerBtnClick = async function ({ data }, tableSelected) {
|
|
209
|
+
|
|
210
|
+
// 权限请求
|
|
211
|
+
await request({
|
|
212
|
+
// 按钮数据
|
|
213
|
+
data,
|
|
214
|
+
// 表格选中数据
|
|
215
|
+
tableSelected,
|
|
216
|
+
// 表格实例
|
|
217
|
+
$table: _data.$table,
|
|
218
|
+
// 表单实例
|
|
219
|
+
$form: _data.$form,
|
|
220
|
+
// 检查是否正在上传文件
|
|
221
|
+
checkUploading,
|
|
222
|
+
|
|
223
|
+
// 请求前执行
|
|
224
|
+
requestBefore: o.requestBefore,
|
|
225
|
+
// 请求成功执行
|
|
226
|
+
requestSuccess: o.requestSuccess,
|
|
227
|
+
// 请求失败执行
|
|
228
|
+
requestFail: o.requestFail,
|
|
229
|
+
// 请求后执行
|
|
230
|
+
requestAfter: o.requestAfter,
|
|
231
|
+
})
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// 如果没有开启权限
|
|
237
|
+
if (! o.power) {
|
|
238
|
+
// 当前页面权限
|
|
239
|
+
data.powerPage = {}
|
|
240
|
+
// 当前页面权限按钮
|
|
241
|
+
data.powerBtns = ref([])
|
|
242
|
+
// 当前页面工具栏权限按钮
|
|
243
|
+
data.toolbarPowerBtns = ref([])
|
|
244
|
+
// 权限按钮点击
|
|
245
|
+
data.powerBtnClick = ()=>{}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// 更新数据
|
|
249
|
+
data.update = function(cb) {
|
|
250
|
+
cb(data, _data)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// 提供可以被后代组件注入的值
|
|
254
|
+
provide(NPowerKey, data)
|
|
255
|
+
|
|
256
|
+
return data
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* 设置权限数据
|
|
8
261
|
*/
|
|
9
262
|
function setData(data) {
|
|
10
263
|
|
|
@@ -167,8 +420,8 @@ function setData(data) {
|
|
|
167
420
|
}
|
|
168
421
|
}
|
|
169
422
|
|
|
170
|
-
//
|
|
171
|
-
|
|
423
|
+
// 保存至权限状态中
|
|
424
|
+
statePower.value = {
|
|
172
425
|
// 角色权限版本
|
|
173
426
|
v,
|
|
174
427
|
// all id
|
|
@@ -183,18 +436,18 @@ function setData(data) {
|
|
|
183
436
|
}
|
|
184
437
|
|
|
185
438
|
/**
|
|
186
|
-
*
|
|
439
|
+
* 获取权限
|
|
187
440
|
*/
|
|
188
441
|
async function getData() {
|
|
189
442
|
|
|
190
|
-
//
|
|
191
|
-
if (!
|
|
443
|
+
// 如果没有权限数据
|
|
444
|
+
if (! statePower.value.v) {
|
|
192
445
|
|
|
193
|
-
//
|
|
194
|
-
const res = await utils.getData(utils.config('
|
|
446
|
+
// 获取权限数据
|
|
447
|
+
const res = await utils.getData(utils.config('powerName'))
|
|
195
448
|
if (res === false) {
|
|
196
|
-
|
|
197
|
-
//
|
|
449
|
+
statePower.value = {
|
|
450
|
+
// 权限版本
|
|
198
451
|
v: null,
|
|
199
452
|
// all id
|
|
200
453
|
all: {},
|
|
@@ -209,9 +462,9 @@ async function getData() {
|
|
|
209
462
|
}
|
|
210
463
|
}
|
|
211
464
|
|
|
212
|
-
//
|
|
213
|
-
if (
|
|
214
|
-
return utils.success(_.cloneDeep(
|
|
465
|
+
// 如果有权限状态数据, 则直接返回
|
|
466
|
+
if (statePower.value.v) {
|
|
467
|
+
return utils.success(_.cloneDeep(statePower.value))
|
|
215
468
|
}
|
|
216
469
|
|
|
217
470
|
return utils.fail()
|
|
@@ -291,13 +544,13 @@ function parseQuery(data, settings) {
|
|
|
291
544
|
}
|
|
292
545
|
|
|
293
546
|
/**
|
|
294
|
-
*
|
|
547
|
+
* 格式化权限按钮
|
|
295
548
|
*/
|
|
296
|
-
function
|
|
549
|
+
function formatBtns(powerBtns, filterBtns, toObject = false) {
|
|
297
550
|
|
|
298
551
|
const newLists = []
|
|
299
552
|
|
|
300
|
-
utils.forEach(
|
|
553
|
+
utils.forEach(powerBtns, function(item) {
|
|
301
554
|
|
|
302
555
|
const {
|
|
303
556
|
name,
|
|
@@ -456,25 +709,15 @@ function formatQuery(query, isJoinArr) {
|
|
|
456
709
|
async function request(params) {
|
|
457
710
|
|
|
458
711
|
// 参数
|
|
459
|
-
const o =
|
|
712
|
+
const o = Object.assign({
|
|
460
713
|
// 按钮数据
|
|
461
714
|
data: {},
|
|
462
715
|
// 参数
|
|
463
716
|
query: {},
|
|
464
|
-
// 布局数据
|
|
465
|
-
layoutData: {},
|
|
466
717
|
// 表格选中数据
|
|
467
718
|
tableSelected: [],
|
|
468
|
-
// 表格刷新
|
|
469
|
-
tableRefresh: null,
|
|
470
719
|
// 检查是否正在上传文件
|
|
471
720
|
checkUploading: null,
|
|
472
|
-
// 表单节点
|
|
473
|
-
formRef: null,
|
|
474
|
-
// 表单数据
|
|
475
|
-
formData: null,
|
|
476
|
-
// 重置表单
|
|
477
|
-
resetForm: null,
|
|
478
721
|
// 请求前执行
|
|
479
722
|
requestBefore: null,
|
|
480
723
|
// 请求成功执行
|
|
@@ -550,50 +793,29 @@ async function request(params) {
|
|
|
550
793
|
// --------------------------------------------------
|
|
551
794
|
if (o.data.type === dicts.POWER_DATA_TYPE__FORM) {
|
|
552
795
|
|
|
796
|
+
// 获取表单注入
|
|
797
|
+
o.$form = _.has(params, '$form') ? params.$form : inject(NFormKey)
|
|
798
|
+
|
|
799
|
+
if (! o.$form) {
|
|
800
|
+
throw new Error('没有创建表单实例')
|
|
801
|
+
}
|
|
802
|
+
|
|
553
803
|
// 如果验证表单
|
|
554
804
|
if (_.get(o.data, 'validate') !== false) {
|
|
555
805
|
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
if (isRef(o.formRef)) {
|
|
559
|
-
formRef = o.formRef.value
|
|
560
|
-
} else if (_.isFunction(o.formRef)) {
|
|
561
|
-
formRef = o.formRef()
|
|
562
|
-
} else {
|
|
563
|
-
formRef = o.formRef
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
// 如果没有绑定表单节点
|
|
568
|
-
if (! formRef) {
|
|
569
|
-
|
|
570
|
-
// 【调试模式】
|
|
571
|
-
// --------------------------------------------------
|
|
572
|
-
// #ifdef IS_DEBUG
|
|
573
|
-
console.log('没有绑定 fromRef')
|
|
574
|
-
// #endif
|
|
575
|
-
// --------------------------------------------------
|
|
576
|
-
|
|
577
|
-
return
|
|
806
|
+
if (! o.$form.formRef) {
|
|
807
|
+
throw new Error('没有绑定 fromRef')
|
|
578
808
|
}
|
|
579
809
|
|
|
580
810
|
// 验证表单
|
|
581
|
-
if (! await formRef.validate()) {
|
|
811
|
+
if (! await o.$form.formRef.value.validate()) {
|
|
582
812
|
return
|
|
583
813
|
}
|
|
584
814
|
}
|
|
585
815
|
|
|
586
|
-
//
|
|
587
|
-
if (! utils.isValidObject(o.formData)) {
|
|
588
|
-
|
|
589
|
-
// 【调试模式】
|
|
590
|
-
// --------------------------------------------------
|
|
591
|
-
// #ifdef IS_DEBUG
|
|
592
|
-
console.log('没有获取到表单数据')
|
|
593
|
-
// #endif
|
|
594
|
-
// --------------------------------------------------
|
|
595
|
-
|
|
596
|
-
return
|
|
816
|
+
// 验证表单数据
|
|
817
|
+
if (! utils.isValidObject(o.$form.formData.value)) {
|
|
818
|
+
throw new Error('没有获取到表单数据')
|
|
597
819
|
}
|
|
598
820
|
|
|
599
821
|
// 检查是否正在上传文件
|
|
@@ -606,11 +828,14 @@ async function request(params) {
|
|
|
606
828
|
}
|
|
607
829
|
|
|
608
830
|
// 获取请求数据
|
|
609
|
-
requestData = _.merge({}, formatQuery(query, false), o.formData)
|
|
831
|
+
requestData = _.merge({}, formatQuery(query, false), o.$form.formData.value)
|
|
610
832
|
|
|
611
833
|
// 如果是请求数据
|
|
612
834
|
// --------------------------------------------------
|
|
613
835
|
} else {
|
|
836
|
+
// 获取表格注入
|
|
837
|
+
o.$table = _.has(params, '$table') ? params.$table : inject(NTableKey)
|
|
838
|
+
|
|
614
839
|
// 获取请求数据
|
|
615
840
|
requestData = formatQuery(query, false)
|
|
616
841
|
}
|
|
@@ -710,12 +935,12 @@ async function request(params) {
|
|
|
710
935
|
|
|
711
936
|
// 重置表单
|
|
712
937
|
case 'resetForm':
|
|
713
|
-
utils.run(o
|
|
938
|
+
utils.run(o.$form?.resetForm)()
|
|
714
939
|
break
|
|
715
940
|
|
|
716
941
|
// 刷新表格
|
|
717
942
|
case 'refreshTable':
|
|
718
|
-
utils.run(o
|
|
943
|
+
utils.run(o.$table?.tableRefresh)()
|
|
719
944
|
break
|
|
720
945
|
}
|
|
721
946
|
}
|
|
@@ -743,65 +968,47 @@ async function request(params) {
|
|
|
743
968
|
/**
|
|
744
969
|
* 获取当前页面角色权限
|
|
745
970
|
*/
|
|
746
|
-
|
|
971
|
+
function getPageData($route) {
|
|
747
972
|
|
|
748
973
|
if (! $route) {
|
|
749
|
-
$route =
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
function fail(message) {
|
|
753
|
-
|
|
754
|
-
if (! _.isNil(pageStatus) && isRef(pageStatus)) {
|
|
755
|
-
pageStatus.value = false
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
if (! _.isNil(emptyDescription) && isRef(emptyDescription)) {
|
|
759
|
-
emptyDescription.value = message
|
|
760
|
-
|
|
761
|
-
} else {
|
|
762
|
-
// 提示框
|
|
763
|
-
utils.alert({
|
|
764
|
-
message,
|
|
765
|
-
})
|
|
766
|
-
}
|
|
767
|
-
return false
|
|
974
|
+
$route = utils.router.getRoute()
|
|
768
975
|
}
|
|
769
976
|
|
|
770
977
|
const path = _.get($route, 'path')
|
|
771
978
|
if (! path) {
|
|
772
|
-
return fail('路由参数错误')
|
|
979
|
+
return utils.fail('路由参数错误')
|
|
773
980
|
}
|
|
774
981
|
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
if (! status || ! _.has(urls, path)) {
|
|
778
|
-
return fail('该页面没有权限')
|
|
982
|
+
if (! statePower.value.v) {
|
|
983
|
+
return utils.fail('没有获取到权限数据')
|
|
779
984
|
}
|
|
780
985
|
|
|
781
|
-
//
|
|
782
|
-
const
|
|
783
|
-
if (! _.
|
|
784
|
-
|
|
986
|
+
// 获取角色数据
|
|
987
|
+
const { urls, btns } = _.cloneDeep(statePower.value)
|
|
988
|
+
if (! _.has(urls, path)) {
|
|
989
|
+
return utils.fail('该页面没有权限')
|
|
785
990
|
}
|
|
786
991
|
|
|
787
|
-
return {
|
|
992
|
+
return utils.success({
|
|
788
993
|
page: urls[path],
|
|
789
|
-
btns:
|
|
790
|
-
}
|
|
994
|
+
btns: _.has(btns, path) ? btns[path] : [],
|
|
995
|
+
})
|
|
791
996
|
}
|
|
792
997
|
|
|
793
998
|
/**
|
|
794
|
-
*
|
|
999
|
+
* 权限业务
|
|
795
1000
|
*/
|
|
796
|
-
utils.$
|
|
797
|
-
//
|
|
1001
|
+
utils.$power = {
|
|
1002
|
+
// 创建
|
|
1003
|
+
create,
|
|
1004
|
+
// 设置权限数据
|
|
798
1005
|
setData,
|
|
799
|
-
//
|
|
1006
|
+
// 获取权限数据
|
|
800
1007
|
getData,
|
|
801
|
-
//
|
|
1008
|
+
// 获取页面权限数据
|
|
802
1009
|
getPageData,
|
|
803
|
-
//
|
|
804
|
-
|
|
1010
|
+
// 格式化权限按钮
|
|
1011
|
+
formatBtns,
|
|
805
1012
|
// 请求
|
|
806
1013
|
request,
|
|
807
1014
|
}
|