修改了对应bug

This commit is contained in:
chenze 2024-08-30 00:42:34 +08:00
parent 2265c9b986
commit 1041344017
4 changed files with 253 additions and 205 deletions

View File

@ -46,7 +46,7 @@
</a-col>
<a-col :md="5" :sm="15">
<a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="请选择状态">
<a-select v-model="queryParam.status"
<a-select v-model="queryParam.type"
v-decorator="['status']">
<a-select-option v-for="item in options" :key="item.value">
{{ item.label }}
@ -65,6 +65,16 @@
</a-form-item>
</a-col>
<a-col :md="5" :sm="15">
<a-form-item label="评价">
<a-select v-model="queryParam.evalService"
v-decorator="['evalService']">
<a-select-option v-for="item in evalOptions" :key="item.value">
{{ item.label }}
</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :md="5" :sm="15">
<a-form-item label="时间范围">
<a-range-picker v-model="dateRange" @change="onChange" />
@ -73,7 +83,7 @@
<a-col :md="8" :sm="24">
<span class="table-page-search-submitButtons">
<a-button type="primary" @click="selectRepairList()">查询</a-button>
<a-button style="margin-left: 8px" @click="() => queryParam = {}">重置</a-button>
<a-button style="margin-left: 8px" @click="reset()">重置</a-button>
<a-button style="margin-left: 8px" type="primary" @click="exportRepair()">导出工单模版</a-button>
<a-button style="margin-left: 8px" type="primary" @click="importDataVisible()">导入</a-button>
<a-button style="margin-left: 8px" type="primary" @click="exportRepairList()">导出工单数据</a-button>
@ -192,34 +202,45 @@ export default {
label: '五级'
}
],
evalOptions: [{
value: '1',
label: '好评'
}, {
value: '2',
label: '中评'
}, {
value: '3',
label: '差评'
}
],
remarkOption: [{
value: '',
value: 'no',
label: '普通报修'
}, {
value: '5110',
value: 'yes',
label: '5110'
}
],
options: [{
value: '1',
label: '待分配'
value: 'wait',
label: '待派单'
}, {
value: '3',
value: 'anew',
label: '重新派单'
}, {
value: '5',
value: 'already',
label: '已派单'
}, {
value: '7',
value: 'process',
label: '处理中'
}, {
value: '9',
value: 'evaling',
label: '已完成,待评价'
}, {
value: '11',
label: '已关闭'
value: 'invalid',
label: '无效申请'
}, {
value: '13',
value: 'evaled',
label: '已评价'
}
],
@ -292,14 +313,19 @@ export default {
}
},
created () {
console.log('this.$route.query', this.$route.query)
this.queryParam.status = this.$route.query.status
console.log('this.$route.query', this.$route.query.evalService)
this.queryParam.evalService = this.$route.query.evalService
this.queryParam.timeout = this.$route.query.timeout
this.selectRepairList()
this.selectType()
},
methods: {
customChange () {
},
reset () {
this.queryParam = {}
this.selectRepairList()
},
customRequest (file) {
// file
@ -381,12 +407,19 @@ export default {
console.log(this.queryParam.typeId)
},
getDeviceName (item) {
console.log(item)
this.deviceName = item.label
this.queryParam.deviceId = item.key
},
//
selectRepairList () {
let type = 'all'
if (this.queryParam.type != null) {
type = this.queryParam.type
}
if (this.$route.query.status != null) {
type = this.$route.query.status
}
if (this.$route.query.repairUserId != null) {
oneWorkerList({ workerId: this.$route.query.repairUserId }).then(res => {
this.loadData = res.rows
@ -400,10 +433,10 @@ export default {
this.loadData = res.rows
})
} else {
console.log(this.deviceId)
let datas = {
'role': 7,
'type': 'all',
'type': type,
'repair': {
'explain': this.queryParam.explain,
'typeId': this.queryParam.typeId,
@ -411,7 +444,10 @@ export default {
'status': this.queryParam.status,
'repairLevel': this.queryParam.repairLevel,
'beginTime': this.queryParam.startTime,
'endTime': this.queryParam.endTime
'endTime': this.queryParam.endTime,
'evalService': this.queryParam.evalService,
'timeout': this.queryParam.timeout,
'remark': this.queryParam.remark
}
}
getRepairList(datas).then(res => {

View File

@ -17,7 +17,7 @@
</a-row>
</a-form>
</div>
<a-tabs :default-active-key="tabKey" @change="callback">
<a-tabs :active-key="tabKey" @change="callback">
<a-tab-pane key="1" tab="全部信息">
<a-table
size="default"
@ -147,7 +147,7 @@ export default {
},
created () {
this.tabKey = this.$route.query.tabKey
if (this.$route.query.tabKey != null) this.tabKey = this.$route.query.tabKey
this.workerList()
},
methods: {
@ -162,8 +162,8 @@ export default {
})
},
callback () {
callback (value) {
this.tabKey = value
},
handleAdd () {

View File

@ -1,73 +1,73 @@
<template>
<a-card :bordered='false'>
<div class='table-page-search-wrapper'>
<a-form layout='inline'>
<a-row :gutter='48'>
<a-col :md='5' :sm='15'>
<a-form-item label='报修单号'>
<a-input placeholder='请输入报修单号' v-model='queryParam.sn' />
<a-card :bordered="false">
<div class="table-page-search-wrapper">
<a-form layout="inline">
<a-row :gutter="48">
<a-col :md="5" :sm="15">
<a-form-item label="报修单号">
<a-input placeholder="请输入报修单号" v-model="queryParam.sn" />
</a-form-item>
</a-col>
<a-col :md='5' :sm='15'>
<a-form-item label='时间范围'>
<a-range-picker v-model='queryParam.timeRange' @change='selectTime' />
<a-col :md="5" :sm="15">
<a-form-item label="时间范围">
<a-range-picker v-model="timeRange" @change="selectTime" />
</a-form-item>
</a-col>
<a-col :md='8' :sm='24'>
<span class='table-page-search-submitButtons'>
<a-button type='primary' @click='$refs.table.refresh(true)'>查询</a-button>
<a-button style='margin-left: 8px' @click='() => queryParam = {}'>重置</a-button>
<a-col :md="8" :sm="24">
<span class="table-page-search-submitButtons">
<a-button type="primary" @click="selectList()">查询</a-button>
<a-button style="margin-left: 8px" @click="() => queryParam = {}">重置</a-button>
</span>
</a-col>
</a-row>
</a-form>
</div>
<a-tabs default-active-key='1' @change='callback'>
<a-tab-pane key='1' tab='维修人员'>
<a-tabs default-active-key="1" @change="callback">
<a-tab-pane key="1" tab="维修人员">
<a-table
size='default'
ref='table'
rowKey='id'
:columns='columns'
:data-source='workerData'
size="default"
ref="table"
rowKey="id"
:columns="columns"
:data-source="workerData"
>
<span slot='status' slot-scope='text'>
<span slot="status" slot-scope="text">
{{ text | statusFilter }}
</span>
<span slot='action' slot-scope='text, record'>
<a v-if='editEnabel' @click='handleView(record.id)'>详情</a>
<span slot="action" slot-scope="text, record">
<a v-if="editEnabel" @click="handleView(record.id)">详情</a>
</span>
</a-table>
</a-tab-pane>
<a-tab-pane key='2' tab='网格区域' force-render>
<a-tab-pane key="2" tab="网格区域" force-render>
<a-table
size='default'
ref='table'
rowKey='id'
:columns='floorColumns'
:data-source='floorData'
size="default"
ref="table"
rowKey="id"
:columns="floorColumns"
:data-source="floorData"
>
<span slot='status' slot-scope='text'>
<span slot="status" slot-scope="text">
{{ text | statusFilter }}
</span>
<span slot='action' slot-scope='text, record'>
<a v-if='editEnabel' @click='handleFloorView(record.id)'>详情</a>
<span slot="action" slot-scope="text, record">
<a v-if="editEnabel" @click="handleFloorView(record.id)">详情</a>
</span>
</a-table>
</a-tab-pane>
<a-tab-pane key='3' tab='网格长'>
<a-tab-pane key="3" tab="网格长">
<a-table
size='default'
ref='table'
rowKey='id'
:columns='floorCreateColumns'
:data-source='floorCreateData'
size="default"
ref="table"
rowKey="id"
:columns="floorCreateColumns"
:data-source="floorCreateData"
>
<span slot='status' slot-scope='text'>
<span slot="status" slot-scope="text">
{{ text | statusFilter }}
</span>
<span slot='action' slot-scope='text, record'>
<a v-if='editEnabel' @click='handleFloorCreateView(record.id)'>详情</a>
<span slot="action" slot-scope="text, record">
<a v-if="editEnabel" @click="handleFloorCreateView(record.id)">详情</a>
</span>
</a-table>
</a-tab-pane>
@ -85,7 +85,7 @@ export default {
components: {
STable
},
data() {
data () {
return {
labelCol: {
xs: { span: 24 },
@ -241,13 +241,14 @@ export default {
editEnabel: checkPermission('admin:repair:edit'),
removeEnable: checkPermission('admin:repair:list'),
loadData: [],
timeRange: '',
workerData: [],
floorData: [],
floorCreateData: []
}
},
filters: {
statusFilter(status) {
statusFilter (status) {
const statusMap = {
'PENDING_ASSIGN': '待分配',
'PENDING_PROCESS': '待处理',
@ -258,59 +259,64 @@ export default {
return statusMap[status]
}
},
created() {
created () {
this.workerList()
this.floorList()
this.floorCreateList()
},
methods: {
selectList () {
this.workerList(this.queryParam)
this.floorList(this.queryParam)
this.floorCreateList(this.queryParam)
},
//
selectTime(value, dateString) {
this.queryParam.startTime = dateString[0]
this.queryParam.endTime = dateString[1]
selectTime (value, dateString) {
this.queryParam.startDate = dateString[0]
this.queryParam.endDate = dateString[1]
console.log('this.queryParam', this.queryParam)
},
// admin/repair/stats/workerList
workerList() {
getWorkerList().then(res => {
workerList (query) {
getWorkerList(query).then(res => {
this.workerData = res.rows
})
},
floorList() {
getFloorList().then(res => {
floorList (query) {
getFloorList(query).then(res => {
this.floorData = res.rows
})
},
floorCreateList() {
getFloorCreateList().then(res => {
floorCreateList (query) {
getFloorCreateList(query).then(res => {
this.floorCreateData = res.rows
})
},
callback() {
callback () {
},
handleAdd() {
handleAdd () {
this.$refs.modal.add()
},
handleView(workerId) {
handleView (workerId) {
this.$router.push({ name: 'repair', query: { repairUserId: workerId } })
},
handleFloorView(floorId) {
handleFloorView (floorId) {
console.log(floorId)
this.$router.push({ name: 'repair', query: { floorId: floorId } })
},
handleFloorCreateView(floorId) {
handleFloorCreateView (floorId) {
this.$router.push({ name: 'repair', query: { floorCreateId: floorId } })
},
handleEdit(record) {
handleEdit (record) {
this.$refs.modal.edit(record)
},
handleOk() {
handleOk () {
this.$refs.table.refresh(true)
console.log('handleSaveOk')
},
handleComplete(id) {
handleComplete (id) {
const _this = this
this.$confirm({
title: '警告',
@ -318,7 +324,7 @@ export default {
okText: '是',
okType: 'warning',
cancelText: '否',
onOk() {
onOk () {
complete(id).then(res => {
if (res.code === 0) {
_this.$message.success('操作成功')
@ -330,7 +336,7 @@ export default {
this.$message.error('系统错误,请稍后再试')
})
},
onCancel() {
onCancel () {
}
})
}

View File

@ -1,152 +1,152 @@
<template>
<div class='container'>
<div class="container">
<div class='topHeadView'>
<div class='itemView' @click="dispatchCase('1')">
<div class='imgView'
<div class="topHeadView">
<div class="itemView" @click="dispatchCase('wait')">
<div class="imgView"
:style="{'background' : `no-repeat center/60px 60px url(${baseUrl + '/img/paidan.png'}), white`}"></div>
<div class='label'>待派单</div>
<div class='num'>{{ adminStatsCount.wait }}</div>
<div class="label">待派单</div>
<div class="num">{{ adminStatsCount.wait }}</div>
</div>
<div class='itemView' @click="dispatchCase('3')">
<div class='imgContainer'>
<div class='imgView'
<div class="itemView" @click="dispatchCase('anew')">
<div class="imgContainer">
<div class="imgView"
:style="{'background' : `no-repeat center/60px 60px url(${baseUrl + '/img/paidanjump.png'}), white`}"></div>
</div>
<div class='label'>重派单</div>
<div class='num'>{{ adminStatsCount.anew }}</div>
<div class="label">重派单</div>
<div class="num">{{ adminStatsCount.anew }}</div>
</div>
<div class='itemView' @click="jumpInfo('2')">
<div class='imgView'
<div class="itemView" @click="jumpInfo('2')">
<div class="imgView"
:style="{'background' : `no-repeat center/60px 60px url(${baseUrl + '/img/time.png'}), white`}"></div>
<div class='label'>未查看通知</div>
<div class='num'>{{ adminStatsCount.newnotice }}</div>
<div class="label">未查看通知</div>
<div class="num">{{ adminStatsCount.newnotice }}</div>
</div>
<div class='itemView' @click="jumpInfo('3')">
<div class='imgView'
<div class="itemView" @click="jumpInfo('3')">
<div class="imgView"
:style="{'background' : `no-repeat center/60px 60px url(${baseUrl + '/img/info.png'}), white`}"></div>
<div class='label'>已查看通知</div>
<div class='num'>{{ adminStatsCount.oldnotice }}</div>
<div class="label">已查看通知</div>
<div class="num">{{ adminStatsCount.oldnotice }}</div>
</div>
</div>
<div class='caseStatisticsView'>
<div class='headView'>
<div class='titleView'>工单统计</div>
<div class='typeView' style='width: 200px;'>
<a-range-picker v-model='dateRange2' @change='onChange2' />
<div class="caseStatisticsView">
<div class="headView">
<div class="titleView">工单统计</div>
<div class="typeView" style="width: 200px;">
<a-range-picker v-model="dateRange2" @change="onChange2" />
</div>
</div>
<div class='contentView'>
<div class='itemView' @click='dispatchCase()'>
<div class='label'>维修工单</div>
<div class='value'>{{ repairStatsCount.zs }}</div>
<div class="contentView">
<div class="itemView" @click="dispatchCase('all')">
<div class="label">维修工单</div>
<div class="value">{{ repairStatsCount.zs }}</div>
</div>
<div class='itemView' @click="dispatchCase('7')">
<div class='label'>处理中工单</div>
<div class='value'>{{ repairStatsCount.wait }}</div>
<div class="itemView" @click="dispatchCase('process')">
<div class="label">处理中工单</div>
<div class="value">{{ repairStatsCount.wait }}</div>
</div>
<div class='itemView' @click='dispatchCase()'>
<div class='label'>超时量</div>
<div class='value'>{{ repairStatsCount.timeout }}</div>
<div class="itemView" @click="dispatchTimeOut(9)">
<div class="label">超时量</div>
<div class="value">{{ repairStatsCount.timeout }}</div>
</div>
<div class='itemView' @click='dispatchCase()'>
<div class='label'>差评量</div>
<div class='value'>{{ repairStatsCount.l }}</div>
<div class="itemView" @click="dispatchEval(3)">
<div class="label">差评量</div>
<div class="value">{{ repairStatsCount.l }}</div>
</div>
<div class='itemView' @click='dispatchCase()'>
<div class='label'>中评量</div>
<div class='value'>{{ repairStatsCount.m }}</div>
<div class="itemView" @click="dispatchEval(2)">
<div class="label">中评量</div>
<div class="value">{{ repairStatsCount.m }}</div>
</div>
<div class='itemView' @click='dispatchCase()'>
<div class='label'>好评量</div>
<div class='value'>{{ repairStatsCount.h }}</div>
<div class="itemView" @click="dispatchEval(1)">
<div class="label">好评量</div>
<div class="value">{{ repairStatsCount.h }}</div>
</div>
</div>
</div>
<div class='statusView'>
<div class='caseStatusView'>
<div class='headView'>
<div class='titleView'>工单完成情况</div>
<div class='typeView' style='width: 200px;'>
<a-range-picker v-model='dateRange3L' @change='onChange3L' />
<div class="statusView">
<div class="caseStatusView">
<div class="headView">
<div class="titleView">工单完成情况</div>
<div class="typeView" style="width: 200px;">
<a-range-picker v-model="dateRange3L" @change="onChange3L" />
</div>
</div>
<div class='contentView'>
<div class='circularView'>
<div id='echart1' style='width: 400px; height: 300px'></div>
<div class="contentView">
<div class="circularView">
<div id="echart1" style="width: 400px; height: 300px"></div>
</div>
<div class='centerLine'></div>
<div class='circularView'>
<div id='echart2' style='width: 400px; height: 300px'></div>
<div class="centerLine"></div>
<div class="circularView">
<div id="echart2" style="width: 400px; height: 300px"></div>
</div>
</div>
</div>
<div class='evaluateView'>
<div class='headView'>
<div class='titleView'>评价情况</div>
<div class='typeView' style='width: 200px;'>
<a-range-picker v-model='dateRange3R' @change='onChange3R' />
<div class="evaluateView">
<div class="headView">
<div class="titleView">评价情况</div>
<div class="typeView" style="width: 200px;">
<a-range-picker v-model="dateRange3R" @change="onChange3R" />
</div>
</div>
<div class='contentView'>
<div id='echart3' style='width: 400px; height: 300px'></div>
<div class="contentView">
<div id="echart3" style="width: 400px; height: 300px"></div>
</div>
</div>
</div>
<div class='faultView'>
<div class='floorView'>
<div class='headView'>
<div class='titleView'>网格长</div>
<div class='typeView' style='width: 200px;'>
<a-range-picker v-model='dateRange4L' @change='onChange4L' />
<div class="faultView">
<div class="floorView">
<div class="headView">
<div class="titleView">网格长</div>
<div class="typeView" style="width: 200px;">
<a-range-picker v-model="dateRange4L" @change="onChange4L" />
</div>
</div>
<div class='contentView'>
<div id='echart4' style='width: 550px; height: 600px'></div>
<div class="contentView">
<div id="echart4" style="width: 550px; height: 600px"></div>
</div>
</div>
<div class='rightView'>
<div class='blockView'>
<div class='headView'>
<div class='titleView'>故障统计</div>
<div class='typeView' style='width: 200px;'>
<a-range-picker v-model='dateRange4R1' @change='onChange4R1' />
<div class="rightView">
<div class="blockView">
<div class="headView">
<div class="titleView">故障统计</div>
<div class="typeView" style="width: 200px;">
<a-range-picker v-model="dateRange4R1" @change="onChange4R1" />
</div>
</div>
<div class='contentView'>
<div id='echart5' style='width: 700px; height: 327px'></div>
<div class="contentView">
<div id="echart5" style="width: 700px; height: 327px"></div>
</div>
</div>
<div class='blockView'>
<div class='headView'>
<div class='titleView'>故障类型</div>
<div class='typeView' style='width: 200px;'>
<a-range-picker v-model='dateRange4R2' @change='onChange4R2' />
<div class="blockView">
<div class="headView">
<div class="titleView">故障类型</div>
<div class="typeView" style="width: 200px;">
<a-range-picker v-model="dateRange4R2" @change="onChange4R2" />
</div>
</div>
<div class='contentView'>
<div id='echart6' style='width: 700px; height: 327px'></div>
<div class="contentView">
<div id="echart6" style="width: 700px; height: 327px"></div>
</div>
</div>
</div>
</div>
<div class='tableView'>
<div class='headView'>
<div class='titleView'>项目详情</div>
<div class='typeView' style='width: 200px;'>
<a-range-picker v-model='dateRange5' @change='onChange5' />
<div class="tableView">
<div class="headView">
<div class="titleView">项目详情</div>
<div class="typeView" style="width: 200px;">
<a-range-picker v-model="dateRange5" @change="onChange5" />
</div>
</div>
<div class='contentView'>
<div class="contentView">
<a-table
size='default'
ref='table'
style='width: 100%'
:columns='columns'
:data-source='loadData'
size="default"
ref="table"
style="width: 100%"
:columns="columns"
:data-source="loadData"
>
</a-table>
@ -178,7 +178,7 @@ export default {
components: {
STable
},
data() {
data () {
return {
dateRange2: [initStart, initEnd],
dateRange3L: [initStart, initEnd],
@ -261,7 +261,7 @@ export default {
loadData: []
}
},
mounted() {
mounted () {
this.adminStats()//
this.repairCount2()//
this.repairCount3L()//
@ -273,47 +273,53 @@ export default {
},
methods: {
//
dispatchCase(status) {
dispatchCase (status) {
this.$router.push({ name: 'repair', query: { status } })
},
//
jumpInfo(tabKey) {
jumpInfo (tabKey) {
this.$router.push({ name: 'messageNotice', query: { tabKey } })
},
onChange2() {
dispatchEval (evalService) {
this.$router.push({ name: 'repair', query: { evalService } })
},
dispatchTimeOut (timeout) {
this.$router.push({ name: 'repair', query: { timeout } })
},
onChange2 () {
this.repairCount2()
},
onChange3L() {
onChange3L () {
this.repairCount3L()
},
onChange3R() {
onChange3R () {
this.repairCount3R()
},
onChange4L() {
onChange4L () {
this.floorStats()
},
onChange4R1() {
onChange4R1 () {
this.deviceStats()
},
onChange4R2() {
onChange4R2 () {
this.failureStats()
},
onChange5() {
onChange5 () {
this.deviceTypeStats()
},
adminStats() {
adminStats () {
repairAdminStats().then(res => {
this.adminStatsCount = res.repairAdminStats
})
},
repairCount2() {
repairCount2 () {
const startDate = this.dateRange2[0].format('YYYY-MM-DD')
const endDate = this.dateRange2[1].format('YYYY-MM-DD')
repairStats({ startDate: startDate, endDate: endDate, type: 'repair' }).then(res => {
this.repairStatsCount = res.data.stats
})
},
repairCount3L() {
repairCount3L () {
const startDate = this.dateRange3L[0].format('YYYY-MM-DD')
const endDate = this.dateRange3L[1].format('YYYY-MM-DD')
repairStats({ startDate: startDate, endDate: endDate, type: 'end' }).then(res => {
@ -331,7 +337,7 @@ export default {
}, ['#ef6567', '#fc8251', '#f9c956', '#91cd77'], this.timeout)
})
},
repairCount3R() {
repairCount3R () {
const startDate = this.dateRange3R[0].format('YYYY-MM-DD')
const endDate = this.dateRange3R[1].format('YYYY-MM-DD')
repairStats({ startDate: startDate, endDate: endDate, type: 'eval' }).then(res => {
@ -344,7 +350,7 @@ export default {
})
},
//
floorStats() {
floorStats () {
const startDate = this.dateRange4L[0].format('YYYY-MM-DD')
const endDate = this.dateRange4L[1].format('YYYY-MM-DD')
floorStats({ startDate: startDate, endDate: endDate }).then(res => {
@ -352,7 +358,7 @@ export default {
})
},
//
deviceStats() {
deviceStats () {
const startDate = this.dateRange4R1[0].format('YYYY-MM-DD')
const endDate = this.dateRange4R1[1].format('YYYY-MM-DD')
deviceStats({ startDate: startDate, endDate: endDate }).then(res => {
@ -361,7 +367,7 @@ export default {
})
},
//
failureStats() {
failureStats () {
const startDate = this.dateRange4R2[0].format('YYYY-MM-DD')
const endDate = this.dateRange4R2[1].format('YYYY-MM-DD')
failureStats({ startDate: startDate, endDate: endDate }).then(res => {
@ -374,7 +380,7 @@ export default {
})
},
//
deviceTypeStats() {
deviceTypeStats () {
const startDate = this.dateRange5[0].format('YYYY-MM-DD')
const endDate = this.dateRange5[1].format('YYYY-MM-DD')
deviceTypeStats({ startDate: startDate, endDate: endDate }).then(res => {
@ -382,7 +388,7 @@ export default {
})
},
createEchartCake(id, legend, colors, data) {
createEchartCake (id, legend, colors, data) {
//console.log(data)
// domecharts
let myChart = echarts.init(document.getElementById(id))
@ -427,7 +433,7 @@ export default {
myChart.setOption(option)
}
,
createEchartLine(id, data) {
createEchartLine (id, data) {
// domecharts
let myChart = echarts.init(document.getElementById(id))
let option = {
@ -472,7 +478,7 @@ export default {
myChart.setOption(option)
}
,
createColumnEcharrt(id, data) {
createColumnEcharrt (id, data) {
data.x = data.x.map(item => {
if (item && item.length > 4) {
item = item.substring(0, 4) + '..'