10525542
王彪总
feat(map): 替换腾讯地图...
|
1
2
3
4
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
|
<template>
<div class="repair-container">
<el-card shadow="never" class="search-card">
<el-form :inline="true" :model="searchForm" size="small">
<el-form-item label="工单状态">
<el-select v-model="searchForm.status" placeholder="全部状态" clearable @change="handleSearch">
<el-option label="待接单" value="PENDING" />
<el-option label="维修中" value="REPAIRING" />
<el-option label="已完成" value="COMPLETED" />
<el-option label="已取消" value="CANCELLED" />
</el-select>
</el-form-item>
<el-form-item label="维修人员">
<el-select v-model="searchForm.repairerId" placeholder="全部" filterable clearable>
<el-option v-for="user in engineerList" :key="user.user_id"
:label="user.name" :value="user.user_id" />
</el-select>
</el-form-item>
<el-form-item label="时间范围">
<el-date-picker v-model="dateRange" type="datetimerange"
range-separator="至" start-placeholder="开始" end-placeholder="结束"
format="yyyy-MM-dd HH:mm:ss" value-format="yyyy-MM-dd HH:mm:ss" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch" icon="el-icon-search">查询</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card shadow="never">
<div slot="header"><span>工单列表(共 {{ pagination.total }} 条)</span></div>
<el-table :data="tableData" border stripe size="small" v-loading="loading">
<el-table-column prop="title" label="工单标题" min-width="180" />
<el-table-column prop="submitter_name" label="提交人" width="100" />
<el-table-column prop="repair_location" label="报修位置" min-width="180" />
<el-table-column prop="repairer_name" label="维修人" width="100" />
<el-table-column prop="status" label="状态" width="100">
<template slot-scope="scope">
<el-tag :type="statusTagType(scope.row.status)" size="small">
{{ statusLabel(scope.row.status) }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="create_time" label="创建时间" width="180" />
<el-table-column label="操作" width="180" fixed="right">
<template slot-scope="scope">
<el-button type="text" size="small" @click="showDetail(scope.row)">详情</el-button>
<el-button v-if="scope.row.status === 'PENDING'"
type="text" size="small" @click="handleAssign(scope.row)">分配</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
style="margin-top: 16px; text-align: right;"
@size-change="handleSizeChange" @current-change="handlePageChange"
:current-page="pagination.page" :page-sizes="[10, 20, 50, 100]"
:page-size="pagination.row" :total="pagination.total"
layout="total, sizes, prev, pager, next, jumper" />
</el-card>
<!-- 工单详情对话框 -->
<el-dialog title="工单详情" :visible.sync="detailVisible" width="600px">
<el-descriptions :column="2" border size="small" v-if="currentOrder">
<el-descriptions-item label="工单标题">{{ currentOrder.title }}</el-descriptions-item>
<el-descriptions-item label="状态">
<el-tag :type="statusTagType(currentOrder.status)" size="small">
{{ statusLabel(currentOrder.status) }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="提交人">{{ currentOrder.submitter_name }}</el-descriptions-item>
<el-descriptions-item label="维修人">{{ currentOrder.repairer_name || '未分配' }}</el-descriptions-item>
<el-descriptions-item label="报修位置">{{ currentOrder.repair_location }}</el-descriptions-item>
<el-descriptions-item label="坐标">{{ currentOrder.longitude }}, {{ currentOrder.latitude }}</el-descriptions-item>
<el-descriptions-item label="问题描述" :span="2">{{ currentOrder.description }}</el-descriptions-item>
<el-descriptions-item label="报修图片" :span="2">
<template v-if="parseImages(currentOrder.images).length">
<el-image v-for="(url, i) in parseImages(currentOrder.images)" :key="i"
:src="url" style="width: 80px; height: 80px; margin-right: 8px;"
:preview-src-list="parseImages(currentOrder.images)" fit="cover" />
</template>
<span v-else>无</span>
</el-descriptions-item>
<el-descriptions-item label="维修结果" :span="2">{{ currentOrder.repair_result || '暂无' }}</el-descriptions-item>
<el-descriptions-item label="结果图片" :span="2">
<template v-if="parseImages(currentOrder.result_images).length">
<el-image v-for="(url, i) in parseImages(currentOrder.result_images)" :key="i"
:src="url" style="width: 80px; height: 80px; margin-right: 8px;"
:preview-src-list="parseImages(currentOrder.result_images)" fit="cover" />
</template>
<span v-else>无</span>
</el-descriptions-item>
<el-descriptions-item label="创建时间">{{ currentOrder.create_time }}</el-descriptions-item>
<el-descriptions-item label="完成时间">{{ currentOrder.complete_time || '未完成' }}</el-descriptions-item>
</el-descriptions>
</el-dialog>
<!-- 分配维修人员对话框 -->
<el-dialog title="分配维修人员" :visible.sync="assignVisible" width="400px">
<el-select v-model="assignForm.repairerId" placeholder="选择维修人员" style="width: 100%">
<el-option v-for="user in engineerList" :key="user.user_id"
:label="user.name" :value="user.user_id" />
</el-select>
<span slot="footer">
<el-button @click="assignVisible = false">取消</el-button>
<el-button type="primary" @click="confirmAssign">确认分配</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { queryRepairOrders, updateRepairStatus } from '@/api/property/propertyApi'
import { queryPropertyUsers } from '@/api/property/propertyApi'
export default {
name: 'RepairOrderView',
data() {
return {
searchForm: { status: '', repairerId: '' },
dateRange: [],
engineerList: [],
tableData: [],
loading: false,
pagination: { page: 1, row: 20, total: 0 },
detailVisible: false,
currentOrder: null,
assignVisible: false,
assignForm: { orderId: '', repairerId: '' }
}
},
mounted() { this.loadEngineers(); this.handleSearch() },
methods: {
statusLabel(s) {
const map = { PENDING: '待接单', REPAIRING: '维修中', COMPLETED: '已完成', CANCELLED: '已取消' }
return map[s] || s
},
statusTagType(s) {
const map = { PENDING: 'warning', REPAIRING: 'primary', COMPLETED: 'success', CANCELLED: 'info' }
return map[s] || 'info'
},
async loadEngineers() {
try {
const res = await queryPropertyUsers({ workType: 'ENGINEERING', page: 1, row: 200 })
this.engineerList = res.data && res.data.data || []
} catch (e) { console.error(e) }
},
async handleSearch() {
this.loading = true
try {
const params = { page: this.pagination.page, row: this.pagination.row, ...this.searchForm }
Object.keys(params).forEach(k => { if (!params[k]) delete params[k] })
if (this.dateRange && this.dateRange.length === 2) {
params.startTime = this.dateRange[0]
params.endTime = this.dateRange[1]
}
const res = await queryRepairOrders(params)
this.tableData = res.data && res.data.data || []
this.pagination.total = res.data && res.data.total || 0
} catch (e) {
this.$message.error('查询失败')
} finally { this.loading = false }
},
/** 解析JSON数组格式的图片URL */
parseImages(images) {
if (!images) return []
try { return JSON.parse(images) } catch (e) { return [] }
},
showDetail(row) { this.currentOrder = row; this.detailVisible = true },
handleAssign(row) {
this.assignForm.orderId = row.id
this.assignForm.repairerId = row.repairer_id || ''
this.assignVisible = true
},
async confirmAssign() {
if (!this.assignForm.repairerId) { this.$message.warning('请选择维修人员'); return }
try {
await updateRepairStatus({
id: this.assignForm.orderId,
status: 'REPAIRING',
repairerId: this.assignForm.repairerId
})
this.$message.success('分配成功')
this.assignVisible = false
this.handleSearch()
} catch (e) { this.$message.error('分配失败') }
},
handleSizeChange(val) { this.pagination.row = val; this.handleSearch() },
handlePageChange(val) { this.pagination.page = val; this.handleSearch() }
}
}
</script>
<style scoped>
.repair-container { padding: 16px; }
.search-card { margin-bottom: 16px; }
</style>
|