|
|
@ -50,6 +50,10 @@ |
|
|
|
<i class="iconfont icon-xinzeng" /> |
|
|
|
新增 |
|
|
|
</el-button> |
|
|
|
<el-button v-permission="permission.edit" size="mini" :disabled="crud.selections.length !== 1" @click="toEdit(crud.selections)"> |
|
|
|
<i class="iconfont icon-bianji" /> |
|
|
|
编辑 |
|
|
|
</el-button> |
|
|
|
</template> |
|
|
|
<template v-slot:middle> |
|
|
|
<el-button slot="reference" size="mini" :loading="crud.delAllLoading" :disabled="crud.selections.length === 0" @click="toDelete(crud.selections)"> |
|
|
@ -58,7 +62,7 @@ |
|
|
|
</el-button> |
|
|
|
</template> |
|
|
|
<template v-slot:right> |
|
|
|
<el-button type="primary" size="mini" :disabled="crud.selections.length !== 1" @click="openBindShelf"><i class="iconfont icon-bangding" />书架绑定</el-button> |
|
|
|
<el-button type="primary" size="mini" :disabled="activeRightBtn" @click="openBindShelf('')"><i class="iconfont icon-bangding" />书架绑定</el-button> |
|
|
|
</template> |
|
|
|
</crudOperation> |
|
|
|
</div> |
|
|
@ -69,32 +73,37 @@ |
|
|
|
<!--表格渲染--> |
|
|
|
<el-table ref="table" v-loading="crud.loading" :data="crud.data" style="width: 100%;" @row-click="clickRowHandler" @selection-change="crud.selectionChangeHandler"> |
|
|
|
<el-table-column type="selection" align="center" width="55" /> |
|
|
|
<el-table-column prop="deviceTypeId.name" label="设备类型" /> |
|
|
|
<el-table-column prop="deviceType" label="设备类型"> |
|
|
|
<template slot-scope="scope"> |
|
|
|
<span v-if="scope.row.deviceType === 1">球型摄像机</span> |
|
|
|
<span v-else>盘点机器人</span> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
<el-table-column prop="deviceName" label="设备名称" /> |
|
|
|
<el-table-column prop="deviceCode" label="设备编号" /> |
|
|
|
<el-table-column prop="ipv4" label="接口IP" /> |
|
|
|
<el-table-column label="接口IP" prop="ipv4" show-overflow-tooltip> |
|
|
|
<el-table-column prop="deviveCode" label="设备编号" /> |
|
|
|
<!-- <el-table-column prop="ipv4" label="接口IP" /> --> |
|
|
|
<el-table-column prop="ipv4" label="接口IP" show-overflow-tooltip> |
|
|
|
<template slot-scope="scope"> |
|
|
|
<span v-if="scope.row.ipv4"> {{ scope.row.ipv4 }} </span> |
|
|
|
<span v-else>——</span> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
<el-table-column label="端口" prop="devicePort"> |
|
|
|
<el-table-column label="端口" prop="rtsp"> |
|
|
|
<template slot-scope="scope"> |
|
|
|
<span v-if="scope.row.devicePort"> {{ scope.row.devicePort }} </span> |
|
|
|
<span v-if="scope.row.rtsp"> {{ scope.row.rtsp }} </span> |
|
|
|
<span v-else>——</span> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
<el-table-column label="状态" prop="categoryName" align="center"> |
|
|
|
<el-table-column label="状态" prop="deviceState" align="center"> |
|
|
|
<template slot-scope="scope"> |
|
|
|
<span :class="{ 'spk-a': scope.row.deviceState === 1, 'off-line': scope.row.deviceState !== 1 }" /> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
<el-table-column prop="bindShelfNum" label="已绑架位" /> |
|
|
|
<el-table-column prop="fondsId" label="所属机构" /> |
|
|
|
<el-table-column prop="shelfCount" label="已绑架位" /> |
|
|
|
<el-table-column prop="fondsName" label="所属机构" /> |
|
|
|
<el-table-column prop="floorName" label="所属楼层" /> |
|
|
|
<el-table-column prop="areaName" label="所属区域" /> |
|
|
|
<el-table-column :show-overflow-tooltip="true" prop="createTime" label="创建日期"> |
|
|
|
<el-table-column prop="regionName" label="所属区域" /> |
|
|
|
<el-table-column :show-overflow-tooltip="true" prop="createTime" label="创建日期" width="160"> |
|
|
|
<template slot-scope="scope"> |
|
|
|
<div>{{ scope.row.createTime | parseTime }}</div> |
|
|
|
</template> |
|
|
@ -163,8 +172,8 @@ |
|
|
|
<el-form-item label="密码" prop="password" style="margin-right: 0; margin-left: 30px;"> |
|
|
|
<el-input v-model="form.password" /> |
|
|
|
</el-form-item> |
|
|
|
<el-form-item label="备注" prop="remark"> |
|
|
|
<el-input v-model="form.remark" type="textarea" :rows="4" style="width: 585px;" /> |
|
|
|
<el-form-item label="备注" prop="remarks"> |
|
|
|
<el-input v-model="form.remarks" type="textarea" :rows="4" style="width: 585px;" /> |
|
|
|
</el-form-item> |
|
|
|
</el-form> |
|
|
|
<div slot="footer" class="dialog-footer"> |
|
|
@ -185,18 +194,13 @@ |
|
|
|
title="书架绑定" |
|
|
|
> |
|
|
|
<div class="setting-dialog"> |
|
|
|
<!-- @input="changePid" :load-options="loadMenus" --> |
|
|
|
<treeselect |
|
|
|
v-model="floorTreeValue" |
|
|
|
:options="menus" |
|
|
|
<el-select v-model="selectShelf" class="filter-item" placeholder="请选择指定架" style="width: 320px; margin-bottom: 20px;" @change="changeShelfBind"> |
|
|
|
<el-option v-for="(item,index) in bindReigonsTree" :key="index" :label="item.shelfName" :value="item.shelfId" /> |
|
|
|
</el-select> |
|
|
|
|
|
|
|
style="width: 320px; margin-bottom: 20px;" |
|
|
|
placeholder="请选择楼层区域" |
|
|
|
/> |
|
|
|
<div class="transfer-bookshelf"> |
|
|
|
<!-- :filter-method="filterMethod" --> |
|
|
|
<el-transfer |
|
|
|
v-model="value4" |
|
|
|
v-model="bindGirdData" |
|
|
|
style="text-align: left; display: inline-block" |
|
|
|
filterable |
|
|
|
filter-placeholder="请输入关键字检索" |
|
|
@ -208,15 +212,15 @@ |
|
|
|
noChecked: '${total}', |
|
|
|
hasChecked: '${checked}/${total}' |
|
|
|
}" |
|
|
|
:data="data" |
|
|
|
:data="unBindGirdData" |
|
|
|
@change="handleChange" |
|
|
|
> |
|
|
|
<div slot-scope="{ option }" style="display: flex;"> |
|
|
|
<span style="display:block; width: 50px; text-align: center;">{{ option.key }}</span> |
|
|
|
<!-- <span style="display:block; width: 50px; text-align: center;">{{ option.key }}</span> --> |
|
|
|
<span style="display:block; width: 150px;">{{ option.label }}</span> |
|
|
|
</div> |
|
|
|
</el-transfer> |
|
|
|
<el-button class="transfer-footer" :disabled="value4.length===0" size="small" @click="rightCheckedClear"><i class="iconfont icon-shanchu" />清空</el-button> |
|
|
|
<el-button class="transfer-footer" :disabled="bindGirdData.length===0" size="small" @click="rightCheckedClear"><i class="iconfont icon-shanchu" />清空</el-button> |
|
|
|
</div> |
|
|
|
<div slot="footer" class="dialog-footer"> |
|
|
|
<el-button type="text" @click="handleCloseDialog">取消</el-button> |
|
|
@ -233,14 +237,10 @@ |
|
|
|
|
|
|
|
<script> |
|
|
|
import crudDevice from '@/api/deviceVI/index' |
|
|
|
import Treeselect from '@riophae/vue-treeselect' |
|
|
|
import '@riophae/vue-treeselect/dist/vue-treeselect.css' |
|
|
|
// import { LOAD_CHILDREN_OPTIONS } from '@riophae/vue-treeselect' |
|
|
|
import { FetchInitBookShelfList } from '@/api/shelf/index' |
|
|
|
import CRUD, { presenter, header, form, crud } from '@crud/crud' |
|
|
|
import crudOperation from '@crud/CRUD.operation' |
|
|
|
import pagination from '@crud/Pagination' |
|
|
|
// import Treeselect from '@riophae/vue-treeselect' |
|
|
|
import '@riophae/vue-treeselect/dist/vue-treeselect.css' |
|
|
|
|
|
|
|
const defaultForm = { |
|
|
|
'account': null, |
|
|
@ -260,11 +260,11 @@ const defaultForm = { |
|
|
|
} |
|
|
|
export default { |
|
|
|
name: 'Device', |
|
|
|
components: { Treeselect, crudOperation, pagination }, |
|
|
|
components: { crudOperation, pagination }, |
|
|
|
cruds() { |
|
|
|
return CRUD({ title: '设备', url: 'api/device/initDeviceInfoList', sort: [], crudMethod: { ...crudDevice }, optShow: { |
|
|
|
return CRUD({ title: '设备', url: 'api/device/initDeviceInfoList', idField: 'id || deviceId', sort: [], crudMethod: { ...crudDevice }, optShow: { |
|
|
|
add: false, |
|
|
|
edit: true, |
|
|
|
edit: false, |
|
|
|
del: false, |
|
|
|
reset: true, |
|
|
|
download: false, |
|
|
@ -275,17 +275,6 @@ export default { |
|
|
|
}, |
|
|
|
mixins: [presenter(), header(), form(defaultForm), crud()], |
|
|
|
data() { |
|
|
|
const generateData = _ => { |
|
|
|
// disabled: i % 4 === 0 |
|
|
|
const data = [] |
|
|
|
for (let i = 1; i <= 20; i++) { |
|
|
|
data.push({ |
|
|
|
key: i, |
|
|
|
label: `001排A面01架${i}层 ` |
|
|
|
}) |
|
|
|
} |
|
|
|
return data |
|
|
|
} |
|
|
|
return { |
|
|
|
regionTreeData: null, |
|
|
|
defaultProps: { |
|
|
@ -322,20 +311,19 @@ export default { |
|
|
|
], |
|
|
|
selectedDeviceType: '球型摄像机', |
|
|
|
levelNumber: 0, |
|
|
|
btn: 'add', |
|
|
|
unBindGirdData: [], |
|
|
|
bindGirdData: [], |
|
|
|
leftDefaultChecked: [], |
|
|
|
rightDefaultChecked: [], |
|
|
|
permission: { |
|
|
|
add: ['admin', 'device:add'], |
|
|
|
edit: ['admin', 'device:edit'], |
|
|
|
del: ['admin', 'device:del'] |
|
|
|
}, |
|
|
|
floorTreeValue: null, |
|
|
|
menus: [], |
|
|
|
data: generateData(), |
|
|
|
value4: [], |
|
|
|
leftDefaultChecked: [], |
|
|
|
rightDefaultChecked: [], |
|
|
|
filterMethod(query, item) { |
|
|
|
// return item.pinyin.indexOf(query) > -1 |
|
|
|
} |
|
|
|
bindReigonsTree: [], |
|
|
|
selectShelf: null |
|
|
|
} |
|
|
|
}, |
|
|
|
computed: { |
|
|
@ -381,6 +369,14 @@ export default { |
|
|
|
mounted() { |
|
|
|
}, |
|
|
|
methods: { |
|
|
|
normalizer(node) { |
|
|
|
return { |
|
|
|
id: node.id, |
|
|
|
label: node.label, |
|
|
|
children: node.children, |
|
|
|
isDisabled: !node.regionId |
|
|
|
} |
|
|
|
}, |
|
|
|
// tree 数据转换 |
|
|
|
transformData(data) { |
|
|
|
return { |
|
|
@ -400,6 +396,9 @@ export default { |
|
|
|
})) |
|
|
|
} |
|
|
|
}, |
|
|
|
treeSelectInput(value) { |
|
|
|
console.log('treeSelectInput', value) |
|
|
|
}, |
|
|
|
renderContent(h, { node, data, store }) { |
|
|
|
return h('span', [ |
|
|
|
h('el-tooltip', { |
|
|
@ -427,14 +426,6 @@ export default { |
|
|
|
}, |
|
|
|
[CRUD.HOOK.afterRefresh](crud) { |
|
|
|
console.log('data', this.crud.data) |
|
|
|
// this.crud.data = [ |
|
|
|
// { id: 1, deviceTypeId: { name: '网络视频录像机(NVR)' }}, |
|
|
|
// { id: 2, deviceTypeId: { name: '环境监控主机' }}, |
|
|
|
// { id: 3, deviceTypeId: { name: '密集架' }}, |
|
|
|
// { id: 4, deviceTypeId: { name: '通道门' }}, |
|
|
|
// { id: 5, deviceTypeId: { name: '桌面式RFID读写器' }}, |
|
|
|
// { id: 6, deviceTypeId: { name: '手持式RFID读写器' }} |
|
|
|
// ] |
|
|
|
}, |
|
|
|
handleNodeClick(data) { |
|
|
|
this.$nextTick(() => { |
|
|
@ -459,17 +450,21 @@ export default { |
|
|
|
} |
|
|
|
|
|
|
|
this.crud.toQuery() |
|
|
|
const params = { |
|
|
|
'floorId': this.crud.query.floorId, |
|
|
|
'regionId': this.crud.query.regionId |
|
|
|
} |
|
|
|
FetchInitBookShelfList(params).then(res => { |
|
|
|
this.bindReigonsTree = res.content |
|
|
|
console.log('this.bindReigonsTree', this.bindReigonsTree) |
|
|
|
}).catch(() => { |
|
|
|
}) |
|
|
|
} |
|
|
|
}) |
|
|
|
}, |
|
|
|
searchChange(val) { |
|
|
|
if (val) { |
|
|
|
this.search = '' |
|
|
|
// this.options.forEach(option => { |
|
|
|
// if (option.value !== val) { |
|
|
|
// this.crud.query[option.value] = null |
|
|
|
// } |
|
|
|
// }) |
|
|
|
} |
|
|
|
}, |
|
|
|
resetQuery() { |
|
|
@ -477,18 +472,45 @@ export default { |
|
|
|
this.crud.query.search = '' |
|
|
|
this.crud.toQuery() |
|
|
|
}, |
|
|
|
// 新增前初始化部门信息 |
|
|
|
[CRUD.HOOK.beforeToAdd](crud, form) { |
|
|
|
this.crud.form.fondsId = this.regionTreeData[0].id |
|
|
|
this.crud.form.deviceType = this.selectedDeviceType |
|
|
|
if (this.selectedTreeKey.hasOwnProperty('floorId')) { |
|
|
|
this.crud.query.floorId = this.selectedTreeKey.id |
|
|
|
} else if (this.selectedTreeKey.hasOwnProperty('regionId')) { |
|
|
|
this.crud.query.floorId = this.selectedTreeKey.parentFloorId |
|
|
|
} else { |
|
|
|
this.crud.query.floorId = null |
|
|
|
} |
|
|
|
this.crud.form.regionId = this.selectedTreeKey.hasOwnProperty('regionId') ? this.selectedTreeKey.id : null |
|
|
|
}, |
|
|
|
toEdit(row) { |
|
|
|
crudDevice.FetchDeviceById({ 'deviceId': row[0].deviceId }).then(res => { |
|
|
|
if (res) { |
|
|
|
crud.form = res |
|
|
|
this.crud.toEdit(crud.form) |
|
|
|
} |
|
|
|
}) |
|
|
|
}, |
|
|
|
[CRUD.HOOK.beforeToEdit](crud, form, btn) { |
|
|
|
// form.deviceTypeId.name |
|
|
|
this.selectedDeviceType = 1 |
|
|
|
this.btn = 'edit' |
|
|
|
this.addDeviceTitle = '编辑设备 - ' + '球形摄像机' |
|
|
|
}, |
|
|
|
// 提交前做的操作 |
|
|
|
[CRUD.HOOK.afterValidateCU](crud) { |
|
|
|
console.log('form', crud.form) |
|
|
|
this.crud.form.deviceType = this.selectedDeviceType |
|
|
|
this.crud.form.floorId = this.selectedTreeKey.parentFloorId |
|
|
|
this.crud.form.fondsId = this.regionTreeData[0].id |
|
|
|
this.crud.form.regionId = this.selectedTreeKey.id |
|
|
|
if (this.btn === 'add') { |
|
|
|
this.crud.form.deviceType = this.selectedDeviceType |
|
|
|
this.crud.form.floorId = this.selectedTreeKey.parentFloorId |
|
|
|
this.crud.form.fondsId = this.regionTreeData[0].id |
|
|
|
this.crud.form.regionId = this.selectedTreeKey.id |
|
|
|
} |
|
|
|
delete crud.form.fondsName |
|
|
|
delete crud.form.floorName |
|
|
|
delete crud.form.deviceState |
|
|
|
delete crud.form.shelfCount |
|
|
|
delete crud.form.regionName |
|
|
|
return true |
|
|
|
}, |
|
|
|
clickRowHandler(row) { |
|
|
@ -506,16 +528,16 @@ export default { |
|
|
|
this.crud.delAllLoading = true |
|
|
|
const ids = [] |
|
|
|
datas.forEach(val => { |
|
|
|
ids.push(val.id) |
|
|
|
ids.push(val.deviceId) |
|
|
|
}) |
|
|
|
crudDevice.del(ids).then(() => { |
|
|
|
this.crud.notify('删除成功', CRUD.NOTIFICATION_TYPE.SUCCESS) |
|
|
|
this.crud.delAllLoading = false |
|
|
|
this.crud.refresh() |
|
|
|
}).catch(err => { |
|
|
|
this.crud.delAllLoading = false |
|
|
|
console.log(err) |
|
|
|
}) |
|
|
|
// crudDevice.del(ids).then(() => { |
|
|
|
// this.crud.notify('删除成功', CRUD.NOTIFICATION_TYPE.SUCCESS) |
|
|
|
// this.crud.delAllLoading = false |
|
|
|
// this.crud.refresh() |
|
|
|
// }).catch(err => { |
|
|
|
// this.crud.delAllLoading = false |
|
|
|
// console.log(err) |
|
|
|
// }) |
|
|
|
}).catch(() => { |
|
|
|
}) |
|
|
|
}, |
|
|
@ -523,6 +545,7 @@ export default { |
|
|
|
this.$refs.deviceForm.validate((valid) => { |
|
|
|
console.log('valid', valid) |
|
|
|
if (valid) { |
|
|
|
this.btn = 'add' |
|
|
|
this.deviceSelectVisible = false |
|
|
|
this.selectedDeviceType = this.deviceForm.deviceType.id |
|
|
|
this.addDeviceTitle = '新增设备 - ' + this.deviceForm.deviceType.name |
|
|
@ -547,58 +570,86 @@ export default { |
|
|
|
// 关闭弹框 |
|
|
|
// done() |
|
|
|
}, |
|
|
|
openBindShelf() { |
|
|
|
this.value4 = [] |
|
|
|
this.bindBookShelfVisible = true |
|
|
|
changeShelfBind(val) { |
|
|
|
console.log('val', val) |
|
|
|
this.openBindShelf(val) |
|
|
|
}, |
|
|
|
openBindShelf(shelfId) { |
|
|
|
if (this.crud.selections.length !== 1) { |
|
|
|
this.$message({ message: '请选择需要绑定的设备', type: 'error', offset: 8 }) |
|
|
|
return false |
|
|
|
} |
|
|
|
crudDevice.FetchDeviceById({ 'deviceId': this.crud.selections[0].deviceId }).then(res => { |
|
|
|
this.bindBookShelfVisible = true |
|
|
|
const params = { |
|
|
|
'fondsId': res.fondsId, |
|
|
|
'floorId': res.floorId, |
|
|
|
'regionId': res.regionId, |
|
|
|
'shelfId': shelfId |
|
|
|
} |
|
|
|
const params2 = { |
|
|
|
'deviceId': res.id |
|
|
|
} |
|
|
|
Promise.all([ |
|
|
|
crudDevice.FetchUnboundGrid(params), |
|
|
|
crudDevice.FetchBoundGridByDevice(params2) |
|
|
|
]).then(results => { |
|
|
|
console.log('FetchUnboundGrid result:', results[0]) |
|
|
|
console.log('FetchBoundGridByDevice result:', results[1]) |
|
|
|
this.unBindGirdData = results[0].map((item, index) => { |
|
|
|
return { |
|
|
|
id: item.gridId, |
|
|
|
label: item.gridName, |
|
|
|
key: item.gridId, |
|
|
|
shelfId: item.shelfId |
|
|
|
} |
|
|
|
}) |
|
|
|
if (results[1].length !== 0) { |
|
|
|
this.unBindGirdData = [ |
|
|
|
...this.unBindGirdData, |
|
|
|
...results[1].map((item, index) => { |
|
|
|
return { |
|
|
|
id: item.gridId, |
|
|
|
label: item.gridName, |
|
|
|
key: item.gridId, |
|
|
|
shelfId: item.shelfId |
|
|
|
} |
|
|
|
}) |
|
|
|
] |
|
|
|
const movedKeys = results[1].map(item => item.gridId) |
|
|
|
this.bindGirdData = movedKeys |
|
|
|
} else { |
|
|
|
this.bindGirdData = [] |
|
|
|
} |
|
|
|
}).catch(error => { |
|
|
|
console.error('Error fetching grids:', error) |
|
|
|
}) |
|
|
|
}) |
|
|
|
}, |
|
|
|
handleChange(value, direction, movedKeys) { |
|
|
|
console.log(value, direction, movedKeys) |
|
|
|
console.log(value + direction + movedKeys) |
|
|
|
}, |
|
|
|
dialogSaveSeting() { |
|
|
|
// https://www.cnblogs.com/liujiajiablog/p/15818056.html |
|
|
|
this.bindBookShelfVisible = false |
|
|
|
console.log(this.value4) |
|
|
|
const movedIds = this.bindGirdData.map(key => { |
|
|
|
const item = this.unBindGirdData.find(item => item.key === key) |
|
|
|
return item ? item.id : null |
|
|
|
}) |
|
|
|
const params = { |
|
|
|
'deviceId': this.crud.selections[0].deviceId, |
|
|
|
'shelfGridIds': movedIds |
|
|
|
} |
|
|
|
crudDevice.FetchDeviceShelfGridBinding(params).then(res => { |
|
|
|
if (res) { |
|
|
|
this.$message({ message: res, type: 'success', offset: 8 }) |
|
|
|
this.crud.refresh() |
|
|
|
} |
|
|
|
this.bindBookShelfVisible = false |
|
|
|
}) |
|
|
|
}, |
|
|
|
rightCheckedClear() { |
|
|
|
this.value4 = [] |
|
|
|
}, |
|
|
|
changePid() { |
|
|
|
// this.$refs.form.validateField('pid') |
|
|
|
this.bindGirdData = [] |
|
|
|
} |
|
|
|
// getMenus(tree, treeNode, resolve) { |
|
|
|
// const params = { pid: tree.id } |
|
|
|
// setTimeout(() => { |
|
|
|
// crudMenu.getMenus(params).then(res => { |
|
|
|
// resolve(res.content) |
|
|
|
// }) |
|
|
|
// }, 100) |
|
|
|
// }, |
|
|
|
// getSupDepts(id) { |
|
|
|
// crudMenu.getMenuSuperior(id).then(res => { |
|
|
|
// const children = res.map(function(obj) { |
|
|
|
// if (!obj.leaf && !obj.children) { |
|
|
|
// obj.children = null |
|
|
|
// } |
|
|
|
// return obj |
|
|
|
// }) |
|
|
|
// this.menus = [{ id: 0, label: '顶级类目', children: children }] |
|
|
|
// }) |
|
|
|
// }, |
|
|
|
// loadMenus({ action, parentNode, callback }) { |
|
|
|
// if (action === LOAD_CHILDREN_OPTIONS) { |
|
|
|
// crudMenu.getMenusTree(parentNode.id).then(res => { |
|
|
|
// parentNode.children = res.map(function(obj) { |
|
|
|
// if (!obj.leaf) { |
|
|
|
// obj.children = null |
|
|
|
// } |
|
|
|
// return obj |
|
|
|
// }) |
|
|
|
// setTimeout(() => { |
|
|
|
// callback() |
|
|
|
// }, 100) |
|
|
|
// }) |
|
|
|
// } |
|
|
|
// }, |
|
|
|
} |
|
|
|
} |
|
|
|
</script> |
|
|
|