zouyu
7 天以前 f1ee0aa9d6c6c89ee9f0e5d845cd3c64f161aeaf
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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
<template>
  <div class="maintenance-management-container">
    <!-- 顶部操作栏 -->
    <el-card shadow="hover" style="margin-bottom: 20px;">
      <div class="card-header">
        <span>维修管理</span>
        <div class="header-buttons">
          <el-button type="primary" @click="showCreateWorkOrderDialog">
            <el-icon-plus /> 创建工单
          </el-button>
        </div>
      </div>
    </el-card>
 
    <el-row :gutter="20">
      <!-- 左侧:工单列表 -->
      <el-col :span="16">
        <el-card shadow="hover">
          <!-- 工单状态标签页 -->
          <el-tabs v-model="activeTab" @tab-change="handleTabChange">
            <el-tab-pane label="待处理" name="pending"></el-tab-pane>
            <el-tab-pane label="处理中" name="processing"></el-tab-pane>
            <el-tab-pane label="已完成" name="completed"></el-tab-pane>
          </el-tabs>
 
          <!-- 工单列表 -->
          <el-table :data="filteredWorkOrders" stripe style="width: 100%" @row-click="handleWorkOrderClick">
            <el-table-column prop="orderNo" label="工单编号" width="180"></el-table-column>
            <el-table-column prop="deviceName" label="设备名称" width="150"></el-table-column>
            <el-table-column prop="faultType" label="故障类型" width="120"></el-table-column>
            <el-table-column prop="createTime" label="创建时间" width="180"></el-table-column>
            <el-table-column prop="assignee" label="负责人" width="120"></el-table-column>
            <el-table-column prop="priority" label="优先级" width="100">
              <template #default="scope">
                <el-tag :type="scope.row.priority === 'high' ? 'danger' : scope.row.priority === 'medium' ? 'warning' : 'info'">
                  {{ scope.row.priority === 'high' ? '高' : scope.row.priority === 'medium' ? '中' : '低' }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column label="操作" width="150">
              <template #default="scope">
                <el-button size="small" @click="showEditWorkOrderDialog(scope.row)">编辑</el-button>
                <el-button type="danger" size="small" @click="handleDeleteWorkOrder(scope.row.id)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
 
          <!-- 分页 -->
          <div class="pagination-container">
            <el-pagination
              background
              layout="total, sizes, prev, pager, next, jumper"
              :total="filteredWorkOrders.length"
              :current-page="currentPage"
              :page-sizes="[10, 20, 50, 100]"
              :page-size="pageSize"
              @size-change="handleSizeChange"
              @current-change="handleCurrentChange"
            ></el-pagination>
          </div>
        </el-card>
      </el-col>
 
      <!-- 右侧:维修统计和备件推荐 -->
      <el-col :span="8">
        <!-- 维修历史统计 -->
        <el-card shadow="hover" style="margin-bottom: 20px;">
          <template #header>
            <div class="card-header">
              <span>维修历史统计</span>
            </div>
          </template>
          <div class="statistics-content">
            <div class="stat-item">
              <div class="stat-label">本月完成工单</div>
              <div class="stat-value">{{ monthlyCompleted }}</div>
            </div>
            <div class="stat-item">
              <div class="stat-label">平均维修时长</div>
              <div class="stat-value">{{ averageRepairTime }}小时</div>
            </div>
            <div class="stat-item">
              <div class="stat-label">设备故障率</div>
              <div class="stat-value">{{ failureRate }}%</div>
            </div>
            <div class="stat-item">
              <div class="stat-label">常用维修设备</div>
              <div class="stat-value">{{ commonDevice }}</div>
            </div>
          </div>
        </el-card>
 
        <!-- 常用备件关联推荐 -->
        <el-card shadow="hover">
          <template #header>
            <div class="card-header">
              <span>常用备件推荐</span>
            </div>
          </template>
          <div class="spare-parts-content">
            <el-table :data="spareParts" stripe style="width: 100%" size="small">
              <el-table-column prop="name" label="备件名称" width="120"></el-table-column>
              <el-table-column prop="model" label="型号" width="100"></el-table-column>
              <el-table-column prop="stock" label="库存" width="80">
                <template #default="scope">
                  <el-tag :type="scope.row.stock < 10 ? 'danger' : 'success'">
                    {{ scope.row.stock }}
                  </el-tag>
                </template>
              </el-table-column>
              <el-table-column prop="usageCount" label="使用次数" width="80"></el-table-column>
            </el-table>
          </div>
        </el-card>
      </el-col>
    </el-row>
 
    <!-- 创建工单对话框 -->
    <el-dialog v-model="createWorkOrderDialogVisible" title="创建维修工单" width="600px">
      <el-form :model="workOrderForm" :rules="workOrderRules" ref="workOrderFormRef" label-width="100px">
        <el-form-item label="设备" prop="deviceId">
          <el-select v-model="workOrderForm.deviceId" placeholder="请选择设备">
            <el-option
              v-for="device in devices"
              :key="device.id"
              :label="device.name"
              :value="device.id"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="故障类型" prop="faultType">
          <el-input v-model="workOrderForm.faultType" placeholder="请输入故障类型"></el-input>
        </el-form-item>
        <el-form-item label="故障描述" prop="faultDescription">
          <el-input v-model="workOrderForm.faultDescription" type="textarea" placeholder="请详细描述故障情况" :rows="3"></el-input>
        </el-form-item>
        <el-form-item label="优先级" prop="priority">
          <el-select v-model="workOrderForm.priority" placeholder="请选择优先级">
            <el-option label="高" value="high"></el-option>
            <el-option label="中" value="medium"></el-option>
            <el-option label="低" value="low"></el-option>
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="createWorkOrderDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="handleCreateWorkOrder">确定</el-button>
        </span>
      </template>
    </el-dialog>
 
    <!-- 编辑工单对话框 -->
    <el-dialog v-model="editWorkOrderDialogVisible" title="编辑维修工单" width="600px">
      <el-form :model="workOrderForm" :rules="workOrderRules" ref="workOrderFormRef" label-width="100px">
        <el-form-item label="工单编号" disabled>
          <el-input v-model="workOrderForm.orderNo"></el-input>
        </el-form-item>
        <el-form-item label="设备" disabled>
          <el-input v-model="workOrderForm.deviceName"></el-input>
        </el-form-item>
        <el-form-item label="故障类型" disabled>
          <el-input v-model="workOrderForm.faultType"></el-input>
        </el-form-item>
        <el-form-item label="负责人" prop="assignee">
          <el-select v-model="workOrderForm.assignee" placeholder="请选择负责人">
            <el-option
              v-for="user in users"
              :key="user.id"
              :label="user.name"
              :value="user.name"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="维修状态" prop="status">
          <el-select v-model="workOrderForm.status" placeholder="请选择状态">
            <el-option label="待处理" value="pending"></el-option>
            <el-option label="处理中" value="processing"></el-option>
            <el-option label="已完成" value="completed"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="维修结果" prop="repairResult">
          <el-input v-model="workOrderForm.repairResult" type="textarea" placeholder="请填写维修结果" :rows="3"></el-input>
        </el-form-item>
        <el-form-item label="备件使用" prop="usedParts">
          <el-input v-model="workOrderForm.usedParts" type="textarea" placeholder="请填写使用的备件" :rows="2"></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="editWorkOrderDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="handleEditWorkOrder">确定</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>
 
<script setup>
import { ref, computed } from 'vue'
 
// 设备列表
const devices = ref([
  { id: 'D001', name: '空压机A-001' },
  { id: 'D002', name: '冷却塔B-002' },
  { id: 'D003', name: '水泵C-003' },
  { id: 'D004', name: '发电机D-004' },
  { id: 'D005', name: '变压器E-005' }
])
 
// 用户列表(用于分配负责人)
const users = ref([
  { id: 'U001', name: '张三' },
  { id: 'U002', name: '李四' },
  { id: 'U003', name: '王五' },
  { id: 'U004', name: '赵六' }
])
 
// 工单列表数据
const workOrders = ref([
  {
    id: 1,
    orderNo: 'WO20241216001',
    deviceId: 'D001',
    deviceName: '空压机A-001',
    faultType: '压力异常',
    faultDescription: '设备运行时压力超过设定阈值,伴有异常噪音',
    priority: 'high',
    assignee: '',
    status: 'pending',
    repairResult: '',
    usedParts: '',
    createTime: '2024-12-16 14:32:15',
    startTime: '',
    endTime: ''
  },
  {
    id: 2,
    orderNo: 'WO20241216002',
    deviceId: 'D002',
    deviceName: '冷却塔B-002',
    faultType: '温度过高',
    faultDescription: '冷却塔出水温度超过设定值,冷却效果不佳',
    priority: 'medium',
    assignee: '张三',
    status: 'processing',
    repairResult: '',
    usedParts: '',
    createTime: '2024-12-16 14:30:45',
    startTime: '2024-12-16 15:00:00',
    endTime: ''
  },
  {
    id: 3,
    orderNo: 'WO20241215001',
    deviceId: 'D003',
    deviceName: '水泵C-003',
    faultType: '振动过大',
    faultDescription: '水泵运行时振动值超过标准,可能影响设备寿命',
    priority: 'medium',
    assignee: '李四',
    status: 'completed',
    repairResult: '更换了水泵轴承,调整了联轴器,振动值恢复正常',
    usedParts: '轴承×2,联轴器×1',
    createTime: '2024-12-15 08:30:00',
    startTime: '2024-12-15 09:00:00',
    endTime: '2024-12-15 10:45:00'
  },
  {
    id: 4,
    orderNo: 'WO20241214001',
    deviceId: 'D004',
    deviceName: '发电机D-004',
    faultType: '电流异常',
    faultDescription: '发电机运行时电流波动较大,可能存在短路风险',
    priority: 'high',
    assignee: '王五',
    status: 'completed',
    repairResult: '检查并修复了发电机绕组短路问题,电流恢复正常',
    usedParts: '绝缘材料×1,导线×5米',
    createTime: '2024-12-14 14:20:00',
    startTime: '2024-12-14 14:30:00',
    endTime: '2024-12-14 16:15:00'
  },
  {
    id: 5,
    orderNo: 'WO20241213001',
    deviceId: 'D005',
    deviceName: '变压器E-005',
    faultType: '电压波动',
    faultDescription: '变压器输出电压波动较大,影响下游设备运行',
    priority: 'low',
    assignee: '赵六',
    status: 'completed',
    repairResult: '调整了变压器分接开关,电压稳定在正常范围内',
    usedParts: '',
    createTime: '2024-12-13 09:15:00',
    startTime: '2024-12-13 10:00:00',
    endTime: '2024-12-13 11:30:00'
  }
])
 
// 当前激活的标签页(工单状态)
const activeTab = ref('pending')
 
// 分页数据
const currentPage = ref(1)
const pageSize = ref(10)
 
// 对话框状态
const createWorkOrderDialogVisible = ref(false)
const editWorkOrderDialogVisible = ref(false)
 
// 工单表单数据
const workOrderForm = ref({
  id: '',
  orderNo: '',
  deviceId: '',
  deviceName: '',
  faultType: '',
  faultDescription: '',
  priority: 'medium',
  assignee: '',
  status: 'pending',
  repairResult: '',
  usedParts: '',
  createTime: '',
  startTime: '',
  endTime: ''
})
 
// 表单验证规则
const workOrderRules = ref({
  deviceId: [{ required: true, message: '请选择设备', trigger: 'change' }],
  faultType: [{ required: true, message: '请输入故障类型', trigger: 'blur' }],
  faultDescription: [{ required: true, message: '请详细描述故障情况', trigger: 'blur' }],
  priority: [{ required: true, message: '请选择优先级', trigger: 'change' }],
  assignee: [{ required: true, message: '请选择负责人', trigger: 'change' }],
  status: [{ required: true, message: '请选择状态', trigger: 'change' }]
})
 
// 表单引用
const workOrderFormRef = ref(null)
 
// 筛选后的工单列表
const filteredWorkOrders = computed(() => {
  return workOrders.value.filter(order => order.status === activeTab.value)
})
 
// 维修统计数据
const monthlyCompleted = ref(28)
const averageRepairTime = ref(2.5)
const failureRate = ref(3.2)
const commonDevice = ref('空压机A-001')
 
// 常用备件推荐
const spareParts = ref([
  { id: 1, name: '轴承', model: '6308', stock: 15, usageCount: 23 },
  { id: 2, name: '密封件', model: 'MS-25', stock: 8, usageCount: 18 },
  { id: 3, name: '联轴器', model: 'CL-50', stock: 5, usageCount: 12 },
  { id: 4, name: '传感器', model: 'TS-100', stock: 3, usageCount: 15 },
  { id: 5, name: '润滑油', model: 'L-46', stock: 20, usageCount: 30 }
])
 
// 显示创建工单对话框
const showCreateWorkOrderDialog = () => {
  // 重置表单
  workOrderForm.value = {
    id: '',
    orderNo: '',
    deviceId: '',
    deviceName: '',
    faultType: '',
    faultDescription: '',
    priority: 'medium',
    assignee: '',
    status: 'pending',
    repairResult: '',
    usedParts: '',
    createTime: '',
    startTime: '',
    endTime: ''
  }
  createWorkOrderDialogVisible.value = true
}
 
// 显示编辑工单对话框
const showEditWorkOrderDialog = (order) => {
  workOrderForm.value = { ...order }
  editWorkOrderDialogVisible.value = true
}
 
// 处理工单点击
const handleWorkOrderClick = (row) => {
  // 可以在这里添加查看工单详情的逻辑
}
 
// 处理标签页切换
const handleTabChange = (tab) => {
  activeTab.value = tab
  currentPage.value = 1 // 切换标签页时重置页码
}
 
// 处理创建工单
const handleCreateWorkOrder = () => {
  // 模拟创建工单
  const newOrder = {
    ...workOrderForm.value,
    id: workOrders.value.length + 1,
    orderNo: `WO${new Date().getFullYear()}${String(new Date().getMonth() + 1).padStart(2, '0')}${String(new Date().getDate()).padStart(2, '0')}${String(workOrders.value.length + 1).padStart(3, '0')}`,
    deviceName: devices.value.find(d => d.id === workOrderForm.value.deviceId)?.name || '',
    createTime: new Date().toLocaleString(),
    status: 'pending'
  }
  workOrders.value.unshift(newOrder)
  createWorkOrderDialogVisible.value = false
  ElMessage.success('工单创建成功')
}
 
// 处理编辑工单
const handleEditWorkOrder = () => {
  // 模拟编辑工单
  const index = workOrders.value.findIndex(order => order.id === workOrderForm.value.id)
  if (index !== -1) {
    // 如果状态从待处理变为处理中,设置开始时间
    if (workOrders.value[index].status === 'pending' && workOrderForm.value.status === 'processing') {
      workOrderForm.value.startTime = new Date().toLocaleString()
    }
    // 如果状态从处理中变为已完成,设置结束时间
    if (workOrders.value[index].status === 'processing' && workOrderForm.value.status === 'completed') {
      workOrderForm.value.endTime = new Date().toLocaleString()
    }
    workOrders.value[index] = { ...workOrderForm.value }
    editWorkOrderDialogVisible.value = false
    ElMessage.success('工单编辑成功')
  }
}
 
// 处理删除工单
const handleDeleteWorkOrder = (id) => {
  ElMessageBox.confirm('确定要删除该工单吗?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    // 模拟删除工单
    const index = workOrders.value.findIndex(order => order.id === id)
    if (index !== -1) {
      workOrders.value.splice(index, 1)
      ElMessage.success('工单删除成功')
    }
  }).catch(() => {
    // 取消删除
  })
}
 
// 处理分页大小变化
const handleSizeChange = (size) => {
  pageSize.value = size
  currentPage.value = 1
}
 
// 处理当前页变化
const handleCurrentChange = (current) => {
  currentPage.value = current
}
</script>
 
<style scoped>
.maintenance-management-container {
  padding: 20px;
  background-color: #f5f7fa;
  min-height: 100vh;
}
 
.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
 
.header-buttons {
  display: flex;
  gap: 10px;
}
 
.pagination-container {
  display: flex;
  justify-content: flex-end;
  margin-top: 20px;
}
 
.statistics-content {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
  padding: 10px 0;
}
 
.stat-item {
  text-align: center;
  padding: 15px;
  background-color: #fafafa;
  border-radius: 4px;
}
 
.stat-label {
  font-size: 14px;
  color: #606266;
  margin-bottom: 10px;
}
 
.stat-value {
  font-size: 24px;
  font-weight: bold;
  color: #303133;
}
 
.spare-parts-content {
  padding: 10px 0;
}
 
:deep(.el-icon-plus) {
  margin-right: 5px;
}
</style>