|
|
@@ -1,597 +1,357 @@
|
|
|
<!--办结工单-->
|
|
|
<template>
|
|
|
- <div class="completed-orders">
|
|
|
- <!-- 页面头部 -->
|
|
|
- <div class="page-header">
|
|
|
- <div class="header-left">
|
|
|
+ <div class="min-h-screen bg-[#f0f2f6] p-5">
|
|
|
+ <div class="mb-5 flex flex-wrap items-center justify-between gap-3 rounded-2xl bg-white px-6 py-4 shadow-[0_2px_8px_rgba(0,0,0,0.04)]">
|
|
|
+ <div class="flex items-center gap-3">
|
|
|
<el-icon><CircleCheck /></el-icon>
|
|
|
- <span class="title">已办结工单</span>
|
|
|
+ <span class="text-[20px] font-600 text-[#1f2d3d]">已办结工单</span>
|
|
|
<el-tag type="success" effect="dark">已完成 {{ completedOrdersCount }}</el-tag>
|
|
|
</div>
|
|
|
- <div class="header-right">
|
|
|
+ <div class="flex flex-wrap items-center gap-3">
|
|
|
<el-input
|
|
|
- v-model="searchKeyword"
|
|
|
- placeholder="搜索工单编号/案件编号/地址"
|
|
|
- clearable
|
|
|
- :prefix-icon="Search"
|
|
|
- style="width: 260px"
|
|
|
- size="default"
|
|
|
+ v-model="searchKeyword"
|
|
|
+ placeholder="搜索工单编号/案件编号"
|
|
|
+ clearable
|
|
|
+ :prefix-icon="Search"
|
|
|
+ class="w-[260px]"
|
|
|
+ @keyup.enter="loadOrders"
|
|
|
/>
|
|
|
- <el-select v-model="alertLevelFilter" placeholder="报警级别" clearable style="width: 120px" size="default">
|
|
|
- <el-option label="严重" value="critical" />
|
|
|
- <el-option label="一般" value="warning" />
|
|
|
+ <el-select v-model="orderLevelFilter" placeholder="优先级" clearable class="w-[120px]">
|
|
|
+ <el-option label="紧急" :value="1" />
|
|
|
+ <el-option label="一般" :value="2" />
|
|
|
+ <el-option label="低" :value="3" />
|
|
|
</el-select>
|
|
|
<el-date-picker
|
|
|
- v-model="dateRange"
|
|
|
- type="daterange"
|
|
|
- range-separator="至"
|
|
|
- start-placeholder="完成起始"
|
|
|
- end-placeholder="完成结束"
|
|
|
- size="default"
|
|
|
- style="width: 260px"
|
|
|
+ v-model="dateRange"
|
|
|
+ type="daterange"
|
|
|
+ range-separator="至"
|
|
|
+ start-placeholder="办结开始"
|
|
|
+ end-placeholder="办结结束"
|
|
|
+ value-format="YYYY-MM-DD"
|
|
|
+ class="w-[280px]"
|
|
|
/>
|
|
|
- <el-button type="primary" :icon="Refresh" @click="refreshList">刷新</el-button>
|
|
|
- <el-button :icon="Download" @click="exportData">导出</el-button>
|
|
|
+ <el-button type="primary" :icon="Refresh" @click="loadOrders">刷新</el-button>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <!-- 统计卡片 -->
|
|
|
- <div class="stats-cards">
|
|
|
- <div class="stat-card" @click="setTimeFilter('week')" :class="{ active: timeFilter === 'week' }">
|
|
|
- <div class="stat-value">{{ weeklyCompleted }}</div>
|
|
|
- <div class="stat-label">本周办结</div>
|
|
|
- </div>
|
|
|
- <div class="stat-card" @click="setTimeFilter('month')" :class="{ active: timeFilter === 'month' }">
|
|
|
- <div class="stat-value">{{ monthlyCompleted }}</div>
|
|
|
- <div class="stat-label">本月办结</div>
|
|
|
+ <div class="mb-5 flex flex-wrap gap-4">
|
|
|
+ <div
|
|
|
+ class="min-w-[110px] cursor-pointer rounded-xl bg-white px-6 py-3 text-center shadow-[0_1px_4px_rgba(0,0,0,0.05)] transition-all duration-200 hover:-translate-y-[2px] hover:shadow-[0_4px_12px_rgba(0,0,0,0.1)]"
|
|
|
+ :class="timeFilter === 'week' ? 'border-2 border-[#67c23a] bg-[#f0f9f0]' : 'border-2 border-transparent'"
|
|
|
+ @click="setTimeFilter('week')"
|
|
|
+ >
|
|
|
+ <div class="text-[28px] font-bold text-[#2c3e50]">{{ weeklyCompleted }}</div>
|
|
|
+ <div class="mt-1 text-[13px] text-[#606266]">本周办结</div>
|
|
|
</div>
|
|
|
- <div class="stat-card" @click="setTimeFilter('all')" :class="{ active: timeFilter === 'all' }">
|
|
|
- <div class="stat-value">{{ completedOrdersCount }}</div>
|
|
|
- <div class="stat-label">全部办结</div>
|
|
|
+ <div
|
|
|
+ class="min-w-[110px] cursor-pointer rounded-xl bg-white px-6 py-3 text-center shadow-[0_1px_4px_rgba(0,0,0,0.05)] transition-all duration-200 hover:-translate-y-[2px] hover:shadow-[0_4px_12px_rgba(0,0,0,0.1)]"
|
|
|
+ :class="timeFilter === 'month' ? 'border-2 border-[#67c23a] bg-[#f0f9f0]' : 'border-2 border-transparent'"
|
|
|
+ @click="setTimeFilter('month')"
|
|
|
+ >
|
|
|
+ <div class="text-[28px] font-bold text-[#2c3e50]">{{ monthlyCompleted }}</div>
|
|
|
+ <div class="mt-1 text-[13px] text-[#606266]">本月办结</div>
|
|
|
</div>
|
|
|
- <div class="stat-card">
|
|
|
- <div class="stat-value">{{ avgCompletionHours }}</div>
|
|
|
- <div class="stat-label">平均办结时长(小时)</div>
|
|
|
+ <div
|
|
|
+ class="min-w-[110px] cursor-pointer rounded-xl bg-white px-6 py-3 text-center shadow-[0_1px_4px_rgba(0,0,0,0.05)] transition-all duration-200 hover:-translate-y-[2px] hover:shadow-[0_4px_12px_rgba(0,0,0,0.1)]"
|
|
|
+ :class="timeFilter === 'all' ? 'border-2 border-[#67c23a] bg-[#f0f9f0]' : 'border-2 border-transparent'"
|
|
|
+ @click="setTimeFilter('all')"
|
|
|
+ >
|
|
|
+ <div class="text-[28px] font-bold text-[#2c3e50]">{{ completedOrdersCount }}</div>
|
|
|
+ <div class="mt-1 text-[13px] text-[#606266]">全部办结</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <!-- 工单列表 -->
|
|
|
- <div class="order-table-container">
|
|
|
- <el-table
|
|
|
- :data="paginatedOrders"
|
|
|
- stripe
|
|
|
- border
|
|
|
- style="width: 100%"
|
|
|
- v-loading="loading"
|
|
|
- @row-click="handleRowClick"
|
|
|
- >
|
|
|
+ <div class="rounded-2xl bg-white p-4 shadow-[0_2px_8px_rgba(0,0,0,0.04)]">
|
|
|
+ <el-table :data="paginatedOrders" stripe border class="w-full" row-class-name="cursor-pointer" v-loading="loading" @row-click="handleRowClick">
|
|
|
<el-table-column type="index" label="序号" width="55" align="center" />
|
|
|
- <el-table-column prop="code" label="工单编号" width="160" sortable />
|
|
|
- <el-table-column prop="caseCode" label="关联案件编号" width="160" />
|
|
|
- <el-table-column prop="alertLevel" label="报警级别" width="100" align="center">
|
|
|
- <template #default="{ row }">
|
|
|
- <el-tag :type="row.alertLevel === 'critical' ? 'danger' : 'warning'" size="small">
|
|
|
- {{ row.alertLevel === 'critical' ? '严重' : '一般' }}
|
|
|
- </el-tag>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column prop="alertType" label="报警类型" width="120" />
|
|
|
- <el-table-column prop="alertDesc" label="报警描述" min-width="180" show-overflow-tooltip />
|
|
|
- <el-table-column prop="ownerUnit" label="权属单位" width="140" />
|
|
|
- <el-table-column prop="address" label="详细地址" min-width="160" show-overflow-tooltip />
|
|
|
- <el-table-column prop="assignee" label="处置人员" width="120" />
|
|
|
- <el-table-column prop="completeTime" label="办结时间" width="160" sortable />
|
|
|
- <el-table-column prop="completionHours" label="耗时(小时)" width="100" sortable align="center">
|
|
|
- <template #default="{ row }">
|
|
|
- <el-tag :type="row.completionHours <= 24 ? 'success' : row.completionHours <= 48 ? 'warning' : 'danger'" size="small">
|
|
|
- {{ row.completionHours }}
|
|
|
- </el-tag>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column label="满意度" width="120" align="center">
|
|
|
+ <el-table-column prop="orderNo" label="工单编号" min-width="170" />
|
|
|
+ <el-table-column prop="caseNo" label="关联案件编号" min-width="170" />
|
|
|
+ <el-table-column prop="orderLevelText" label="优先级" width="100" align="center">
|
|
|
<template #default="{ row }">
|
|
|
- <el-rate v-model="row.satisfaction" disabled :colors="['#99a9bf', '#f7ba2a', '#ff9900']" />
|
|
|
+ <el-tag :type="row.orderLevelTag" size="small">{{ row.orderLevelText }}</el-tag>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
+ <el-table-column prop="orderTypeText" label="工单类型" width="110" />
|
|
|
+ <el-table-column prop="orderDesc" label="问题描述" min-width="220" show-overflow-tooltip />
|
|
|
+ <el-table-column prop="deviceCode" label="设备编号" width="150" />
|
|
|
+ <el-table-column prop="realFinishTimeText" label="办结时间" width="170" />
|
|
|
<el-table-column label="操作" width="120" fixed="right" align="center">
|
|
|
<template #default="{ row }">
|
|
|
<el-button link type="primary" size="small" @click.stop="viewDetail(row)">查看详情</el-button>
|
|
|
- <el-button link type="success" size="small" @click.stop="viewFeedback(row)">反馈详情</el-button>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
|
|
|
- <!-- 分页 -->
|
|
|
- <div class="pagination-wrapper">
|
|
|
+ <div class="mt-4 flex justify-end border-t border-[#e9ecef] pt-3">
|
|
|
<el-pagination
|
|
|
- background
|
|
|
- layout="total, sizes, prev, pager, next, jumper"
|
|
|
- :total="filteredOrders.length"
|
|
|
- v-model:current-page="currentPage"
|
|
|
- v-model:page-size="pageSize"
|
|
|
- :page-sizes="[10, 20, 50, 100]"
|
|
|
+ background
|
|
|
+ layout="total, sizes, prev, pager, next, jumper"
|
|
|
+ :total="filteredOrders.length"
|
|
|
+ v-model:current-page="currentPage"
|
|
|
+ v-model:page-size="pageSize"
|
|
|
+ :page-sizes="[10, 20, 50]"
|
|
|
/>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <!-- 工单详情抽屉 -->
|
|
|
- <el-drawer v-model="detailDrawerVisible" :title="`工单详情 - ${currentOrder?.code}`" size="550px" direction="rtl">
|
|
|
- <div v-if="currentOrder" class="order-detail">
|
|
|
+ <el-drawer v-model="detailDrawerVisible" :title="`工单详情 - ${currentOrder?.orderNo || ''}`" size="560px" direction="rtl">
|
|
|
+ <div v-if="currentOrder" class="p-2" v-loading="detailLoading">
|
|
|
<el-descriptions :column="1" border>
|
|
|
- <el-descriptions-item label="工单编号">{{ currentOrder.code }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="关联案件">
|
|
|
- <el-link type="primary" @click="viewCaseDetail">{{ currentOrder.caseCode }}</el-link>
|
|
|
+ <el-descriptions-item label="工单ID">{{ currentOrder.orderId || '—' }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="工单编号">{{ currentOrder.orderNo }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="报警ID">{{ currentOrder.alarmId || '—' }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="案件ID">{{ currentOrder.caseId || '—' }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="关联案件编号">{{ currentOrder.caseNo || '—' }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="设备ID">{{ currentOrder.deviceId || '—' }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="设备编号">{{ currentOrder.deviceCode || '—' }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="工单状态">
|
|
|
+ <el-tag :type="currentOrder.orderStatusTag">{{ currentOrder.orderStatusText }}</el-tag>
|
|
|
</el-descriptions-item>
|
|
|
- <el-descriptions-item label="报警级别">
|
|
|
- <el-tag :type="currentOrder.alertLevel === 'critical' ? 'danger' : 'warning'">
|
|
|
- {{ currentOrder.alertLevel === 'critical' ? '严重' : '一般' }}
|
|
|
- </el-tag>
|
|
|
+ <el-descriptions-item label="优先级">
|
|
|
+ <el-tag :type="currentOrder.orderLevelTag">{{ currentOrder.orderLevelText }}</el-tag>
|
|
|
</el-descriptions-item>
|
|
|
- <el-descriptions-item label="报警类型">{{ currentOrder.alertType }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="报警描述">{{ currentOrder.alertDesc }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="权属单位">{{ currentOrder.ownerUnit }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="详细地址">{{ currentOrder.address }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="用途">{{ currentOrder.purpose || '市政排水' }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="处置人员">{{ currentOrder.assignee }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="创建时间">{{ currentOrder.createTime }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="办结时间">{{ currentOrder.completeTime }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="处理耗时">{{ currentOrder.completionHours }} 小时</el-descriptions-item>
|
|
|
- <el-descriptions-item label="满意度评分">
|
|
|
- <el-rate v-model="currentOrder.satisfaction" disabled />
|
|
|
- </el-descriptions-item>
|
|
|
- <el-descriptions-item label="审批意见">{{ currentOrder.approvalRemark || '无' }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="工单类型">{{ currentOrder.orderTypeText }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="问题描述">{{ currentOrder.orderDesc || '—' }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="负责部门ID">{{ currentOrder.deptId || '—' }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="设备类别">{{ currentOrder.equipmentTypeName || '—' }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="接单人ID">{{ currentOrder.receiveUser || '—' }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="派单人ID">{{ currentOrder.dispatchUser || '—' }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="验收人ID">{{ currentOrder.verifyUser || '—' }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="派单时间">{{ currentOrder.dispatchTimeText }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="创建时间">{{ currentOrder.createTimeText }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="计划完成时间">{{ currentOrder.planFinishTimeText }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="延期原因">{{ currentOrder.delayedReason || '—' }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="延期截止时间">{{ currentOrder.delayedDeadlineText }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="验收时间">{{ currentOrder.verifyTimeText }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="办结时间">{{ currentOrder.realFinishTimeText }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="处置结果">{{ currentOrder.repairResult || '—' }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="设备运维状态">{{ currentOrder.currentStatusText }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="设备在线状态">{{ currentOrder.onlineStatusText }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="设备报警状态">{{ currentOrder.alarmStatusText }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="状态更新时间">{{ currentOrder.statusUpdateTimeText }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="更新时间">{{ currentOrder.updateTimeText }}</el-descriptions-item>
|
|
|
</el-descriptions>
|
|
|
|
|
|
- <!-- 处置反馈信息 -->
|
|
|
- <div class="feedback-section" v-if="currentOrder.feedback">
|
|
|
- <div class="sub-title">
|
|
|
- <el-icon><Picture /></el-icon> 现场处置反馈
|
|
|
- </div>
|
|
|
- <el-descriptions :column="1" border size="small">
|
|
|
- <el-descriptions-item label="反馈人员">{{ currentOrder.feedback.workerName }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="反馈时间">{{ currentOrder.feedback.feedbackTime }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="处置说明">{{ currentOrder.feedback.description }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="现场照片">
|
|
|
- <div class="feedback-images">
|
|
|
- <el-image
|
|
|
- v-for="(img, idx) in currentOrder.feedback.images"
|
|
|
- :key="idx"
|
|
|
- :src="img"
|
|
|
- fit="cover"
|
|
|
- class="feedback-img"
|
|
|
- :preview-src-list="currentOrder.feedback.images"
|
|
|
- preview-teleported
|
|
|
- />
|
|
|
- </div>
|
|
|
- </el-descriptions-item>
|
|
|
- </el-descriptions>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 处理记录时间轴 -->
|
|
|
- <div class="process-logs" v-if="currentOrder.processLogs?.length">
|
|
|
- <div class="sub-title">办理经过</div>
|
|
|
- <el-timeline>
|
|
|
- <el-timeline-item v-for="log in currentOrder.processLogs" :key="log.id" :timestamp="log.time" :type="log.type">
|
|
|
- {{ log.content }}
|
|
|
- <span v-if="log.operator" class="operator">操作人: {{ log.operator }}</span>
|
|
|
+ <div class="mt-4">
|
|
|
+ <div class="mb-3 mt-5 text-[15px] font-600 text-[#2c3e50]">办理经过</div>
|
|
|
+ <el-timeline v-if="currentOrder.workOrderLogList?.length">
|
|
|
+ <el-timeline-item
|
|
|
+ v-for="log in currentOrder.workOrderLogList"
|
|
|
+ :key="log.logId"
|
|
|
+ :timestamp="formatDateTime(log.operTime)"
|
|
|
+ :type="getLogType(log.operType)"
|
|
|
+ >
|
|
|
+ {{ log.operDesc }}
|
|
|
+ <span v-if="log.operUserName" class="ml-3 text-[12px] text-[#909399]">操作人: {{ log.operUserName }}</span>
|
|
|
</el-timeline-item>
|
|
|
</el-timeline>
|
|
|
+ <el-empty v-else description="暂无办理日志" :image-size="80" />
|
|
|
</div>
|
|
|
</div>
|
|
|
</el-drawer>
|
|
|
-
|
|
|
- <!-- 反馈详情弹窗 -->
|
|
|
- <el-dialog v-model="feedbackDialogVisible" title="处置反馈详情" width="500px">
|
|
|
- <div v-if="currentFeedback">
|
|
|
- <el-descriptions :column="1" border>
|
|
|
- <el-descriptions-item label="处置人员">{{ currentFeedback.workerName }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="反馈时间">{{ currentFeedback.feedbackTime }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="处置说明">{{ currentFeedback.description }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="现场照片">
|
|
|
- <div class="feedback-images">
|
|
|
- <el-image
|
|
|
- v-for="(img, idx) in currentFeedback.images"
|
|
|
- :key="idx"
|
|
|
- :src="img"
|
|
|
- fit="cover"
|
|
|
- class="feedback-img"
|
|
|
- :preview-src-list="currentFeedback.images"
|
|
|
- preview-teleported
|
|
|
- />
|
|
|
- </div>
|
|
|
- </el-descriptions-item>
|
|
|
- </el-descriptions>
|
|
|
- </div>
|
|
|
- </el-dialog>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { ref, computed } from 'vue'
|
|
|
-import { CircleCheck, Search, Refresh, Download, Picture } from '@element-plus/icons-vue'
|
|
|
-import { ElMessage } from 'element-plus'
|
|
|
-
|
|
|
-// 模拟已办结工单数据
|
|
|
-const mockCompletedOrders = ref([
|
|
|
- {
|
|
|
- id: 1, code: 'WO-20250401-001', caseCode: 'CASE-20250401-001', alertLevel: 'critical',
|
|
|
- alertType: '倾斜超标', alertDesc: '井盖倾斜角度14.2°,超过阈值8°,有跌落风险',
|
|
|
- ownerUnit: '市政工程管理处', address: '人民路与解放路口东50m', purpose: '主干道排水',
|
|
|
- status: 'completed', createTime: '2025-04-01 09:30:00', completeTime: '2025-04-01 16:20:00',
|
|
|
- completionHours: 6.8, assignee: '张建国', satisfaction: 5,
|
|
|
- approvalRemark: '处置及时,井盖已修复加固',
|
|
|
- feedback: {
|
|
|
- workerName: '张建国', feedbackTime: '2025-04-01 15:30:00',
|
|
|
- description: '现场井盖因车辆碾压移位,已复位加固,设备测试正常',
|
|
|
- images: ['https://fuss10.elemecdn.com/1/34/19aa98b1fcb2781c4fba33d850549jpeg.jpeg']
|
|
|
- },
|
|
|
- processLogs: [
|
|
|
- { id: 1, time: '2025-04-01 09:30:00', content: '工单自动创建', type: 'info', operator: '系统' },
|
|
|
- { id: 2, time: '2025-04-01 10:00:00', content: '指派张建国前往处置', type: 'primary', operator: '调度中心' },
|
|
|
- { id: 3, time: '2025-04-01 15:30:00', content: '提交处置反馈', type: 'warning', operator: '张建国' },
|
|
|
- { id: 4, time: '2025-04-01 16:20:00', content: '审批通过,工单办结', type: 'success', operator: '审批人' }
|
|
|
- ]
|
|
|
- },
|
|
|
- {
|
|
|
- id: 2, code: 'WO-20250331-002', caseCode: 'CASE-20250331-002', alertLevel: 'critical',
|
|
|
- alertType: '水位超限', alertDesc: '井下水位62cm,超过阈值40cm,溢水风险',
|
|
|
- ownerUnit: '水务集团', address: '滨江路化工园区南门', purpose: '化工区雨水排放',
|
|
|
- status: 'completed', createTime: '2025-03-31 14:00:00', completeTime: '2025-04-01 09:30:00',
|
|
|
- completionHours: 19.5, assignee: '李志强', satisfaction: 4,
|
|
|
- approvalRemark: '排水作业完成,水位恢复正常',
|
|
|
- feedback: {
|
|
|
- workerName: '李志强', feedbackTime: '2025-04-01 08:00:00',
|
|
|
- description: '使用抽水泵排水,清理管道堵塞物,水位已降至安全线以下',
|
|
|
- images: ['https://fuss10.elemecdn.com/3/5e/4bbf4c1b1b4f1e1c0b4b4c1b1b4f1e1c.jpeg']
|
|
|
- },
|
|
|
- processLogs: [
|
|
|
- { id: 1, time: '2025-03-31 14:00:00', content: '工单创建', type: 'info', operator: '系统' },
|
|
|
- { id: 2, time: '2025-03-31 15:00:00', content: '指派李志强紧急处置', type: 'primary', operator: '调度中心' },
|
|
|
- { id: 3, time: '2025-04-01 08:00:00', content: '提交反馈,申请审批', type: 'warning', operator: '李志强' },
|
|
|
- { id: 4, time: '2025-04-01 09:30:00', content: '审批通过办结', type: 'success', operator: '审批人' }
|
|
|
- ]
|
|
|
- },
|
|
|
- {
|
|
|
- id: 3, code: 'WO-20250330-003', caseCode: 'CASE-20250330-003', alertLevel: 'warning',
|
|
|
- alertType: '异常震动', alertDesc: '异常震动112mg,超过阈值80mg,疑似外力冲击',
|
|
|
- ownerUnit: '市政设施管理处', address: '古城街北段树下', purpose: '老城区排水',
|
|
|
- status: 'completed', createTime: '2025-03-30 10:15:00', completeTime: '2025-03-30 17:00:00',
|
|
|
- completionHours: 6.75, assignee: '王大明', satisfaction: 5,
|
|
|
- approvalRemark: '现场查看为施工影响,已协调施工方注意保护',
|
|
|
- feedback: {
|
|
|
- workerName: '王大明', feedbackTime: '2025-03-30 16:00:00',
|
|
|
- description: '附近有道路施工,大型车辆碾压导致震动,已设置警示标志',
|
|
|
- images: ['https://fuss10.elemecdn.com/1/34/19aa98b1fcb2781c4fba33d850549jpeg.jpeg']
|
|
|
- },
|
|
|
- processLogs: [
|
|
|
- { id: 1, time: '2025-03-30 10:15:00', content: '工单创建', type: 'info', operator: '系统' },
|
|
|
- { id: 2, time: '2025-03-30 11:00:00', content: '指派王大明现场核实', type: 'primary', operator: '调度中心' },
|
|
|
- { id: 3, time: '2025-03-30 16:00:00', content: '反馈处置结果', type: 'warning', operator: '王大明' },
|
|
|
- { id: 4, time: '2025-03-30 17:00:00', content: '审批办结', type: 'success', operator: '审批人' }
|
|
|
- ]
|
|
|
- },
|
|
|
- {
|
|
|
- id: 4, code: 'WO-20250329-004', caseCode: 'CASE-20250329-004', alertLevel: 'warning',
|
|
|
- alertType: '井盖开启异常', alertDesc: '井盖非正常开启',
|
|
|
- ownerUnit: '市政工程管理处', address: '南港路旧车站段', purpose: '市政井盖',
|
|
|
- status: 'completed', createTime: '2025-03-29 08:20:00', completeTime: '2025-03-29 11:30:00',
|
|
|
- completionHours: 3.17, assignee: '陈辉', satisfaction: 4,
|
|
|
- approvalRemark: '误报警,已复位',
|
|
|
- feedback: {
|
|
|
- workerName: '陈辉', feedbackTime: '2025-03-29 10:30:00',
|
|
|
- description: '经核实为附近小孩玩耍误开井盖,已关闭并加装锁扣',
|
|
|
- images: []
|
|
|
- },
|
|
|
- processLogs: [
|
|
|
- { id: 1, time: '2025-03-29 08:20:00', content: '工单创建', type: 'info', operator: '系统' },
|
|
|
- { id: 2, time: '2025-03-29 09:00:00', content: '指派陈辉前往', type: 'primary', operator: '调度中心' },
|
|
|
- { id: 3, time: '2025-03-29 10:30:00', content: '反馈处置', type: 'warning', operator: '陈辉' },
|
|
|
- { id: 4, time: '2025-03-29 11:30:00', content: '审批通过', type: 'success', operator: '审批人' }
|
|
|
- ]
|
|
|
- },
|
|
|
- {
|
|
|
- id: 5, code: 'WO-20250328-005', caseCode: 'CASE-20250328-005', alertLevel: 'critical',
|
|
|
- alertType: '气体超标', alertDesc: '井下H₂S浓度28ppm,超过阈值15ppm',
|
|
|
- ownerUnit: '生态环境局', address: '石化大道南侧', purpose: '化工区排污',
|
|
|
- status: 'completed', createTime: '2025-03-28 13:00:00', completeTime: '2025-03-29 10:00:00',
|
|
|
- completionHours: 21, assignee: '赵志远', satisfaction: 5,
|
|
|
- approvalRemark: '气体浓度已下降至安全范围,持续监测中',
|
|
|
- feedback: {
|
|
|
- workerName: '赵志远', feedbackTime: '2025-03-29 09:00:00',
|
|
|
- description: '检查井内通风,气体已消散,未发现泄漏源',
|
|
|
- images: ['https://fuss10.elemecdn.com/3/5e/4bbf4c1b1b4f1e1c0b4b4c1b1b4f1e1c.jpeg']
|
|
|
- },
|
|
|
- processLogs: [
|
|
|
- { id: 1, time: '2025-03-28 13:00:00', content: '工单创建', type: 'info', operator: '系统' },
|
|
|
- { id: 2, time: '2025-03-28 14:00:00', content: '指派赵志远处置', type: 'primary', operator: '调度中心' },
|
|
|
- { id: 3, time: '2025-03-29 09:00:00', content: '反馈处置', type: 'warning', operator: '赵志远' },
|
|
|
- { id: 4, time: '2025-03-29 10:00:00', content: '审批办结', type: 'success', operator: '审批人' }
|
|
|
- ]
|
|
|
- },
|
|
|
- {
|
|
|
- id: 6, code: 'WO-20250327-006', caseCode: 'CASE-20250327-006', alertLevel: 'warning',
|
|
|
- alertType: '电池低电量', alertDesc: '设备电池电量仅剩12%,需及时更换',
|
|
|
- ownerUnit: '市政设施管理处', address: '中央公园北门', purpose: '公园排水',
|
|
|
- status: 'completed', createTime: '2025-03-27 09:00:00', completeTime: '2025-03-27 15:30:00',
|
|
|
- completionHours: 6.5, assignee: '张建国', satisfaction: 4,
|
|
|
- approvalRemark: '电池已更换,设备恢复',
|
|
|
- feedback: {
|
|
|
- workerName: '张建国', feedbackTime: '2025-03-27 14:30:00',
|
|
|
- description: '已更换新电池,设备电压恢复正常',
|
|
|
- images: []
|
|
|
- },
|
|
|
- processLogs: [
|
|
|
- { id: 1, time: '2025-03-27 09:00:00', content: '工单创建', type: 'info', operator: '系统' },
|
|
|
- { id: 2, time: '2025-03-27 10:00:00', content: '指派张建国', type: 'primary', operator: '调度中心' },
|
|
|
- { id: 3, time: '2025-03-27 14:30:00', content: '反馈并提交审批', type: 'warning', operator: '张建国' },
|
|
|
- { id: 4, time: '2025-03-27 15:30:00', content: '审批通过', type: 'success', operator: '审批人' }
|
|
|
- ]
|
|
|
- }
|
|
|
-])
|
|
|
+import {computed, onMounted, ref} from 'vue'
|
|
|
+import {CircleCheck, Refresh, Search} from '@element-plus/icons-vue'
|
|
|
+import {ElMessage} from 'element-plus'
|
|
|
+import {getManholeWorkOrderDetail, getManholeWorkOrderFinishedPage} from '@/api/pipeNetwork/basic'
|
|
|
|
|
|
-// 筛选条件
|
|
|
+const orders = ref([])
|
|
|
+const loading = ref(false)
|
|
|
+const detailLoading = ref(false)
|
|
|
const searchKeyword = ref('')
|
|
|
-const alertLevelFilter = ref('')
|
|
|
+const orderLevelFilter = ref('')
|
|
|
const dateRange = ref([])
|
|
|
-const timeFilter = ref('all') // week, month, all
|
|
|
+const timeFilter = ref('all')
|
|
|
const currentPage = ref(1)
|
|
|
const pageSize = ref(10)
|
|
|
-const loading = ref(false)
|
|
|
-
|
|
|
-// 弹窗/抽屉状态
|
|
|
const detailDrawerVisible = ref(false)
|
|
|
-const feedbackDialogVisible = ref(false)
|
|
|
const currentOrder = ref(null)
|
|
|
-const currentFeedback = ref(null)
|
|
|
|
|
|
-// 计算属性 - 基础筛选
|
|
|
-const filteredOrders = computed(() => {
|
|
|
- let list = [...mockCompletedOrders.value]
|
|
|
-
|
|
|
- // 报警级别筛选
|
|
|
- if (alertLevelFilter.value) {
|
|
|
- list = list.filter(o => o.alertLevel === alertLevelFilter.value)
|
|
|
- }
|
|
|
-
|
|
|
- // 关键词搜索
|
|
|
- if (searchKeyword.value) {
|
|
|
- const kw = searchKeyword.value.toLowerCase()
|
|
|
- list = list.filter(o =>
|
|
|
- o.code.toLowerCase().includes(kw) ||
|
|
|
- o.caseCode.toLowerCase().includes(kw) ||
|
|
|
- o.address.toLowerCase().includes(kw) ||
|
|
|
- o.assignee.toLowerCase().includes(kw)
|
|
|
- )
|
|
|
- }
|
|
|
-
|
|
|
- // 日期范围筛选
|
|
|
- if (dateRange.value && dateRange.value.length === 2) {
|
|
|
- const start = new Date(dateRange.value[0])
|
|
|
- const end = new Date(dateRange.value[1])
|
|
|
- list = list.filter(o => {
|
|
|
- const completeDate = new Date(o.completeTime)
|
|
|
- return completeDate >= start && completeDate <= end
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- // 时间筛选(本周/本月)
|
|
|
- const now = new Date()
|
|
|
- if (timeFilter.value === 'week') {
|
|
|
- const weekAgo = new Date(now.setDate(now.getDate() - 7))
|
|
|
- list = list.filter(o => new Date(o.completeTime) >= weekAgo)
|
|
|
- } else if (timeFilter.value === 'month') {
|
|
|
- const monthAgo = new Date(now.setMonth(now.getMonth() - 1))
|
|
|
- list = list.filter(o => new Date(o.completeTime) >= monthAgo)
|
|
|
- }
|
|
|
-
|
|
|
- return list
|
|
|
-})
|
|
|
-
|
|
|
-const paginatedOrders = computed(() => {
|
|
|
- const start = (currentPage.value - 1) * pageSize.value
|
|
|
- return filteredOrders.value.slice(start, start + pageSize.value)
|
|
|
-})
|
|
|
-
|
|
|
-// 统计数据
|
|
|
-const completedOrdersCount = computed(() => mockCompletedOrders.value.length)
|
|
|
-const weeklyCompleted = computed(() => {
|
|
|
- const weekAgo = new Date()
|
|
|
- weekAgo.setDate(weekAgo.getDate() - 7)
|
|
|
- return mockCompletedOrders.value.filter(o => new Date(o.completeTime) >= weekAgo).length
|
|
|
-})
|
|
|
-const monthlyCompleted = computed(() => {
|
|
|
- const monthAgo = new Date()
|
|
|
- monthAgo.setMonth(monthAgo.getMonth() - 1)
|
|
|
- return mockCompletedOrders.value.filter(o => new Date(o.completeTime) >= monthAgo).length
|
|
|
-})
|
|
|
-const avgCompletionHours = computed(() => {
|
|
|
- const sum = mockCompletedOrders.value.reduce((acc, o) => acc + o.completionHours, 0)
|
|
|
- return (sum / mockCompletedOrders.value.length).toFixed(1)
|
|
|
-})
|
|
|
-
|
|
|
-// 方法
|
|
|
-const setTimeFilter = (filter) => {
|
|
|
- timeFilter.value = filter
|
|
|
- currentPage.value = 1
|
|
|
-}
|
|
|
-
|
|
|
-const refreshList = () => {
|
|
|
- loading.value = true
|
|
|
- setTimeout(() => {
|
|
|
- loading.value = false
|
|
|
- ElMessage.success('列表已刷新')
|
|
|
- }, 500)
|
|
|
+function formatDateTime(value) {
|
|
|
+ if (!value) return '—'
|
|
|
+ return String(value).replace('T', ' ')
|
|
|
}
|
|
|
|
|
|
-const exportData = () => {
|
|
|
- ElMessage.success('导出工单报表(演示)')
|
|
|
-}
|
|
|
-
|
|
|
-const handleRowClick = (row) => {
|
|
|
- viewDetail(row)
|
|
|
-}
|
|
|
-
|
|
|
-const viewDetail = (order) => {
|
|
|
- currentOrder.value = order
|
|
|
- detailDrawerVisible.value = true
|
|
|
-}
|
|
|
-
|
|
|
-const viewFeedback = (order) => {
|
|
|
- if (order.feedback) {
|
|
|
- currentFeedback.value = order.feedback
|
|
|
- feedbackDialogVisible.value = true
|
|
|
- } else {
|
|
|
- ElMessage.info('暂无反馈详情')
|
|
|
+function getOrderLevelMeta(level) {
|
|
|
+ const map = {
|
|
|
+ 1: { text: '紧急', tag: 'danger' },
|
|
|
+ 2: { text: '一般', tag: 'warning' },
|
|
|
+ 3: { text: '低', tag: 'info' }
|
|
|
}
|
|
|
+ return map[Number(level)] || { text: '—', tag: 'info' }
|
|
|
}
|
|
|
|
|
|
-const viewCaseDetail = () => {
|
|
|
- ElMessage.info(`查看案件 ${currentOrder.value?.caseCode} 详情(演示)`)
|
|
|
-}
|
|
|
-</script>
|
|
|
-
|
|
|
-<style scoped>
|
|
|
-.completed-orders {
|
|
|
- background: #f0f2f6;
|
|
|
- min-height: 100vh;
|
|
|
- padding: 20px;
|
|
|
-}
|
|
|
-
|
|
|
-.page-header {
|
|
|
- background: white;
|
|
|
- border-radius: 16px;
|
|
|
- padding: 16px 24px;
|
|
|
- margin-bottom: 20px;
|
|
|
- display: flex;
|
|
|
- justify-content: space-between;
|
|
|
- align-items: center;
|
|
|
- flex-wrap: wrap;
|
|
|
- gap: 12px;
|
|
|
- box-shadow: 0 2px 8px rgba(0,0,0,0.04);
|
|
|
-}
|
|
|
-
|
|
|
-.header-left {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- gap: 12px;
|
|
|
-}
|
|
|
-
|
|
|
-.header-left .title {
|
|
|
- font-size: 20px;
|
|
|
- font-weight: 600;
|
|
|
- color: #1f2d3d;
|
|
|
-}
|
|
|
-
|
|
|
-.header-right {
|
|
|
- display: flex;
|
|
|
- gap: 12px;
|
|
|
- align-items: center;
|
|
|
- flex-wrap: wrap;
|
|
|
-}
|
|
|
-
|
|
|
-.stats-cards {
|
|
|
- display: flex;
|
|
|
- gap: 16px;
|
|
|
- margin-bottom: 20px;
|
|
|
- flex-wrap: wrap;
|
|
|
-}
|
|
|
-
|
|
|
-.stat-card {
|
|
|
- background: white;
|
|
|
- border-radius: 12px;
|
|
|
- padding: 12px 24px;
|
|
|
- text-align: center;
|
|
|
- cursor: pointer;
|
|
|
- transition: all 0.2s;
|
|
|
- min-width: 110px;
|
|
|
- box-shadow: 0 1px 4px rgba(0,0,0,0.05);
|
|
|
+function getOrderTypeText(type) {
|
|
|
+ const map = {
|
|
|
+ 1: '故障维修',
|
|
|
+ 2: '日常巡检',
|
|
|
+ 3: '设备保养'
|
|
|
+ }
|
|
|
+ return map[Number(type)] || '—'
|
|
|
}
|
|
|
|
|
|
-.stat-card:hover {
|
|
|
- transform: translateY(-2px);
|
|
|
- box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
|
|
+function getOrderStatusMeta(status) {
|
|
|
+ const map = {
|
|
|
+ 6: { text: '已结案', tag: 'success' },
|
|
|
+ 7: { text: '已驳回', tag: 'danger' },
|
|
|
+ 9: { text: '已延期', tag: 'warning' }
|
|
|
+ }
|
|
|
+ return map[Number(status)] || { text: '—', tag: 'info' }
|
|
|
}
|
|
|
|
|
|
-.stat-card.active {
|
|
|
- border: 2px solid #67c23a;
|
|
|
- background: #f0f9f0;
|
|
|
+function getOnlineStatusText(status) {
|
|
|
+ const map = {
|
|
|
+ 0: '离线',
|
|
|
+ 1: '在线'
|
|
|
+ }
|
|
|
+ return map[Number(status)] || '—'
|
|
|
}
|
|
|
|
|
|
-.stat-value {
|
|
|
- font-size: 28px;
|
|
|
- font-weight: bold;
|
|
|
- color: #2c3e50;
|
|
|
+function getAlarmStatusText(status) {
|
|
|
+ const map = {
|
|
|
+ 0: '正常',
|
|
|
+ 1: '报警'
|
|
|
+ }
|
|
|
+ return map[Number(status)] || '—'
|
|
|
}
|
|
|
|
|
|
-.stat-label {
|
|
|
- font-size: 13px;
|
|
|
- color: #606266;
|
|
|
- margin-top: 4px;
|
|
|
+function getCurrentStatusText(status) {
|
|
|
+ const map = {
|
|
|
+ 1: '在用',
|
|
|
+ 2: '闲置',
|
|
|
+ 3: '维修',
|
|
|
+ 4: '报废',
|
|
|
+ 5: '待入库'
|
|
|
+ }
|
|
|
+ return map[Number(status)] || '—'
|
|
|
}
|
|
|
|
|
|
-.order-table-container {
|
|
|
- background: white;
|
|
|
- border-radius: 16px;
|
|
|
- padding: 16px;
|
|
|
- box-shadow: 0 2px 8px rgba(0,0,0,0.04);
|
|
|
+function normalizeOrder(item) {
|
|
|
+ const levelMeta = getOrderLevelMeta(item.orderLevel)
|
|
|
+ const statusMeta = getOrderStatusMeta(item.orderStatus)
|
|
|
+ return {
|
|
|
+ ...item,
|
|
|
+ orderLevelText: levelMeta.text,
|
|
|
+ orderLevelTag: levelMeta.tag,
|
|
|
+ orderTypeText: getOrderTypeText(item.orderType),
|
|
|
+ orderStatusText: statusMeta.text,
|
|
|
+ orderStatusTag: statusMeta.tag,
|
|
|
+ createTimeText: formatDateTime(item.createTime),
|
|
|
+ dispatchTimeText: formatDateTime(item.dispatchTime),
|
|
|
+ planFinishTimeText: formatDateTime(item.planFinishTime),
|
|
|
+ delayedDeadlineText: formatDateTime(item.delayedDeadline),
|
|
|
+ verifyTimeText: formatDateTime(item.verifyTime),
|
|
|
+ realFinishTimeText: formatDateTime(item.realFinishTime),
|
|
|
+ updateTimeText: formatDateTime(item.updateTime),
|
|
|
+ currentStatusText: getCurrentStatusText(item.equipmentStatus?.currentStatus),
|
|
|
+ onlineStatusText: getOnlineStatusText(item.equipmentStatus?.onlineStatus),
|
|
|
+ alarmStatusText: getAlarmStatusText(item.equipmentStatus?.alarmStatus),
|
|
|
+ statusUpdateTimeText: formatDateTime(item.equipmentStatus?.statusUpdateTime)
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-.pagination-wrapper {
|
|
|
- display: flex;
|
|
|
- justify-content: flex-end;
|
|
|
- margin-top: 16px;
|
|
|
- padding-top: 12px;
|
|
|
- border-top: 1px solid #e9ecef;
|
|
|
+function isWithinRecentDays(value, days) {
|
|
|
+ if (!value) return false
|
|
|
+ const time = new Date(value).getTime()
|
|
|
+ if (Number.isNaN(time)) return false
|
|
|
+ return Date.now() - time <= days * 24 * 3600000
|
|
|
}
|
|
|
|
|
|
-.order-detail {
|
|
|
- padding: 8px;
|
|
|
-}
|
|
|
+const filteredOrders = computed(() => {
|
|
|
+ if (timeFilter.value === 'week') {
|
|
|
+ return orders.value.filter(item => isWithinRecentDays(item.realFinishTime, 7))
|
|
|
+ }
|
|
|
+ if (timeFilter.value === 'month') {
|
|
|
+ return orders.value.filter(item => isWithinRecentDays(item.realFinishTime, 30))
|
|
|
+ }
|
|
|
+ return orders.value
|
|
|
+})
|
|
|
|
|
|
-.sub-title {
|
|
|
- font-weight: 600;
|
|
|
- margin: 20px 0 12px 0;
|
|
|
- font-size: 15px;
|
|
|
- color: #2c3e50;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- gap: 8px;
|
|
|
-}
|
|
|
+const paginatedOrders = computed(() => {
|
|
|
+ const start = (currentPage.value - 1) * pageSize.value
|
|
|
+ return filteredOrders.value.slice(start, start + pageSize.value)
|
|
|
+})
|
|
|
|
|
|
-.feedback-images {
|
|
|
- display: flex;
|
|
|
- gap: 12px;
|
|
|
- flex-wrap: wrap;
|
|
|
- margin-top: 8px;
|
|
|
-}
|
|
|
+const completedOrdersCount = computed(() => orders.value.length)
|
|
|
+const weeklyCompleted = computed(() => orders.value.filter(item => isWithinRecentDays(item.realFinishTime, 7)).length)
|
|
|
+const monthlyCompleted = computed(() => orders.value.filter(item => isWithinRecentDays(item.realFinishTime, 30)).length)
|
|
|
|
|
|
-.feedback-img {
|
|
|
- width: 100px;
|
|
|
- height: 80px;
|
|
|
- border-radius: 8px;
|
|
|
- object-fit: cover;
|
|
|
- cursor: pointer;
|
|
|
+async function loadOrders() {
|
|
|
+ loading.value = true
|
|
|
+ try {
|
|
|
+ const keyword = searchKeyword.value.trim()
|
|
|
+ const payload = {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 200,
|
|
|
+ orderLevel: orderLevelFilter.value || undefined,
|
|
|
+ orderNo: keyword || undefined,
|
|
|
+ caseNo: keyword || undefined,
|
|
|
+ startTime: dateRange.value?.[0] ? `${dateRange.value[0]} 00:00:00` : undefined,
|
|
|
+ endTime: dateRange.value?.[1] ? `${dateRange.value[1]} 23:59:59` : undefined
|
|
|
+ }
|
|
|
+ const res = await getManholeWorkOrderFinishedPage(payload)
|
|
|
+ const records = Array.isArray(res?.data?.records) ? res.data.records : []
|
|
|
+ orders.value = records.map(normalizeOrder)
|
|
|
+ currentPage.value = 1
|
|
|
+ if (currentOrder.value) {
|
|
|
+ const matched = orders.value.find(item => item.orderId === currentOrder.value.orderId)
|
|
|
+ if (matched) {
|
|
|
+ await viewDetail(matched)
|
|
|
+ } else {
|
|
|
+ currentOrder.value = null
|
|
|
+ detailDrawerVisible.value = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ orders.value = []
|
|
|
+ currentOrder.value = null
|
|
|
+ ElMessage.error('办结工单加载失败')
|
|
|
+ } finally {
|
|
|
+ loading.value = false
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-.process-logs {
|
|
|
- margin-top: 16px;
|
|
|
+async function viewDetail(order) {
|
|
|
+ detailLoading.value = true
|
|
|
+ detailDrawerVisible.value = true
|
|
|
+ try {
|
|
|
+ const res = await getManholeWorkOrderDetail(order.orderId)
|
|
|
+ currentOrder.value = normalizeOrder(res?.data || order)
|
|
|
+ } catch (error) {
|
|
|
+ currentOrder.value = order
|
|
|
+ ElMessage.error('工单详情加载失败')
|
|
|
+ } finally {
|
|
|
+ detailLoading.value = false
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-.operator {
|
|
|
- font-size: 12px;
|
|
|
- color: #909399;
|
|
|
- margin-left: 12px;
|
|
|
+function handleRowClick(row) {
|
|
|
+ viewDetail(row)
|
|
|
}
|
|
|
|
|
|
-:deep(.el-table__row) {
|
|
|
- cursor: pointer;
|
|
|
+function setTimeFilter(filter) {
|
|
|
+ timeFilter.value = filter
|
|
|
+ currentPage.value = 1
|
|
|
}
|
|
|
|
|
|
-:deep(.el-table__row:hover) {
|
|
|
- background-color: #f5f7fa;
|
|
|
+function getLogType(operType) {
|
|
|
+ const map = {
|
|
|
+ 2: 'primary',
|
|
|
+ 3: 'warning',
|
|
|
+ 4: 'primary',
|
|
|
+ 5: 'warning',
|
|
|
+ 6: 'success',
|
|
|
+ 7: 'danger',
|
|
|
+ 8: 'warning',
|
|
|
+ 9: 'success'
|
|
|
+ }
|
|
|
+ return map[Number(operType)] || 'info'
|
|
|
}
|
|
|
|
|
|
-:deep(.el-rate) {
|
|
|
- display: inline-flex;
|
|
|
-}
|
|
|
-</style>
|
|
|
+onMounted(() => {
|
|
|
+ loadOrders()
|
|
|
+})
|
|
|
+</script>
|