You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4272 lines
176 KiB
HTML

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>设备管理 - 智慧河道管理平台</title>
<!-- <link rel="stylesheet" href="styles.css"> -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="all.min.css">
<link rel="stylesheet" href="/common/plugin/map/ol/v6.12.0/css/ol.css" type="text/css" />
<script src="/common/plugin/map/ol/v6.12.0/build/ol.js"></script>
<style>
/* ==== 全局样式 ==== */
body {
margin: 0;
padding: 0;
font-family: 'Arial', sans-serif;
background-color: #f5f9ff;
color: #333;
}
/* ==== 主容器 ==== */
.main-container {
display: flex;
min-height: 100vh;
padding: 20px;
box-sizing: border-box;
gap: 20px;
}
/* ==== 左侧内容区域 ==== */
.content-area {
flex: 1;
background: #ffffff;
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0, 75, 150, 0.1);
padding: 20px;
display: flex;
flex-direction: column;
overflow: hidden;
}
/* ==== 右侧侧边栏 ==== */
.sidebar-area {
width: 350px;
background: #ffffff;
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0, 75, 150, 0.1);
padding: 20px;
display: flex;
flex-direction: column;
overflow-y: auto;
max-height: calc(100vh - 40px);
}
/* ==== 头部区域 ==== */
.device-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 15px;
border-bottom: 1px solid #e1e9f5;
}
.device-title {
color: #1a4b8c;
font-size: 24px;
font-weight: 600;
}
.device-actions {
display: flex;
gap: 10px;
}
.action-btn {
background: linear-gradient(135deg, #2a7de1, #1a4b8c);
color: #fff;
border: none;
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
transition: all 0.3s ease;
font-size: 14px;
box-shadow: 0 2px 8px rgba(42, 125, 225, 0.2);
}
.action-btn:hover {
background: linear-gradient(135deg, #1a4b8c, #2a7de1);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(42, 125, 225, 0.3);
}
/* ==== 标签页 ==== */
.device-tabs {
display: flex;
background: #e1e9f5;
border-radius: 10px;
padding: 5px;
margin-bottom: 20px;
}
.tab-btn {
flex: 1;
padding: 12px 20px;
background: transparent;
color: #4a6fa5;
border: none;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
font-size: 14px;
font-weight: 500;
}
.tab-btn.active {
background: #ffffff;
color: #1a4b8c;
font-weight: 600;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.tab-content {
display: none;
flex: 1;
overflow-y: auto;
padding-right: 5px;
/* 为滚动条留空间 */
}
.tab-content.active {
display: block;
animation: fadeIn 0.5s ease;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* ==== 设备卡片 ==== */
.device-card {
background: #ffffff;
border-radius: 12px;
padding: 20px;
margin-bottom: 20px;
border: 1px solid #e1e9f5;
box-shadow: 0 2px 10px rgba(0, 75, 150, 0.05);
}
.card-title {
color: #1a4b8c;
font-size: 18px;
font-weight: 600;
margin-bottom: 15px;
display: flex;
align-items: center;
gap: 10px;
}
.card-title i {
color: #2a7de1;
}
/* ==== 表单样式 ==== */
.form-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 15px;
margin-bottom: 20px;
}
.form-group {
display: flex;
flex-direction: column;
}
.form-group label {
color: #4a6fa5;
font-size: 14px;
margin-bottom: 5px;
font-weight: 500;
}
.form-group input,
.form-group select,
.form-group textarea {
background: #f5f9ff;
border: 1px solid #d1e0f5;
border-radius: 6px;
padding: 10px;
color: #1a4b8c;
font-size: 14px;
transition: all 0.3s ease;
}
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
border-color: #2a7de1;
box-shadow: 0 0 0 3px rgba(42, 125, 225, 0.2);
outline: none;
}
.form-group input::placeholder,
.form-group textarea::placeholder {
color: #a8c0e0;
}
/* ==== 表格样式 ==== */
.device-table {
width: 100%;
background: #ffffff;
border-radius: 10px;
overflow: hidden;
border-collapse: separate;
border-spacing: 0;
box-shadow: 0 2px 10px rgba(0, 75, 150, 0.05);
}
.device-table th,
.device-table td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid #e1e9f5;
}
.device-table th {
background: #f5f9ff;
color: #1a4b8c;
font-weight: 600;
font-size: 14px;
}
.device-table td {
color: #4a6fa5;
font-size: 13px;
}
.device-table tr:last-child td {
border-bottom: none;
}
/* ==== 状态标签 ==== */
.status-badge {
padding: 4px 8px;
border-radius: 12px;
font-size: 12px;
font-weight: 500;
text-align: center;
display: inline-block;
min-width: 60px;
}
.status-online {
background: rgba(40, 167, 69, 0.1);
color: #28a745;
border: 1px solid rgba(40, 167, 69, 0.3);
}
.status-offline {
background: rgba(220, 53, 69, 0.1);
color: #dc3545;
border: 1px solid rgba(220, 53, 69, 0.3);
}
.status-maintenance {
background: rgba(255, 193, 7, 0.1);
color: #ffc107;
border: 1px solid rgba(255, 193, 7, 0.3);
}
.status-fault {
background: rgba(220, 53, 69, 0.1);
color: #dc3545;
border: 1px solid rgba(220, 53, 69, 0.3);
}
/* ==== 侧边栏样式 ==== */
.sidebar-section {
background: #f5f9ff;
border-radius: 12px;
padding: 15px;
margin-bottom: 20px;
border: 1px solid #e1e9f5;
}
.sidebar-title {
color: #1a4b8c;
font-size: 16px;
font-weight: 600;
margin-bottom: 15px;
display: flex;
align-items: center;
gap: 8px;
}
.sidebar-title i {
color: #2a7de1;
}
/* ==== 统计卡片 ==== */
.stats-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
margin-bottom: 15px;
}
.stat-item {
background: #ffffff;
padding: 15px;
border-radius: 8px;
text-align: center;
box-shadow: 0 2px 8px rgba(0, 75, 150, 0.05);
border: 1px solid #e1e9f5;
}
.stat-value {
color: #2a7de1;
font-size: 24px;
font-weight: 700;
display: block;
}
.stat-label {
color: #4a6fa5;
font-size: 12px;
margin-top: 5px;
}
/* ==== 图表容器 ==== */
.chart-container {
background: #ffffff;
border-radius: 8px;
padding: 15px;
height: 200px;
display: flex;
align-items: center;
justify-content: center;
color: #a8c0e0;
border: 1px solid #e1e9f5;
box-shadow: 0 2px 8px rgba(0, 75, 150, 0.05);
}
/* ==== 设备网格 ==== */
.device-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
}
.device-item {
background: #ffffff;
border-radius: 12px;
padding: 20px;
border: 1px solid #e1e9f5;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(0, 75, 150, 0.05);
}
.device-item:hover {
transform: translateY(-5px);
box-shadow: 0 8px 20px rgba(0, 75, 150, 0.1);
}
.device-info {
display: flex;
align-items: center;
gap: 15px;
margin-bottom: 15px;
}
.device-icon {
width: 50px;
height: 50px;
background: linear-gradient(135deg, #e1e9f5, #d1e0f5);
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
color: #2a7de1;
}
.device-details h4 {
color: #1a4b8c;
margin: 0 0 5px 0;
font-size: 16px;
}
.device-details p {
color: #4a6fa5;
margin: 0;
font-size: 14px;
}
.device-params {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
margin-bottom: 15px;
}
.param-item {
background: #f5f9ff;
padding: 8px;
border-radius: 6px;
text-align: center;
border: 1px solid #e1e9f5;
}
.param-value {
color: #2a7de1;
font-weight: 600;
display: block;
}
.param-label {
color: #4a6fa5;
font-size: 12px;
}
/* ==== 告警列表 ==== */
.alert-list {
max-height: 300px;
overflow-y: auto;
}
.alert-item {
background: #ffffff;
padding: 12px;
border-radius: 8px;
margin-bottom: 10px;
border-left: 4px solid #dc3545;
box-shadow: 0 2px 8px rgba(0, 75, 150, 0.05);
}
.alert-title {
color: #1a4b8c;
font-size: 14px;
font-weight: 600;
margin-bottom: 5px;
}
.alert-info {
color: #4a6fa5;
font-size: 12px;
display: flex;
justify-content: space-between;
}
/* ==== 按钮样式 ==== */
.btn {
background: #f5f9ff;
color: #2a7de1;
border: 1px solid #d1e0f5;
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
transition: all 0.3s ease;
font-size: 12px;
margin-right: 5px;
}
.btn:hover {
background: #e1e9f5;
}
.btn-primary {
background: rgba(42, 125, 225, 0.1);
color: #2a7de1;
border-color: rgba(42, 125, 225, 0.3);
}
.btn-primary:hover {
background: rgba(42, 125, 225, 0.2);
}
.btn-success {
background: rgba(40, 167, 69, 0.1);
color: #28a745;
border-color: rgba(40, 167, 69, 0.3);
}
.btn-success:hover {
background: rgba(40, 167, 69, 0.2);
}
.btn-danger {
background: rgba(220, 53, 69, 0.1);
color: #dc3545;
border-color: rgba(220, 53, 69, 0.3);
}
.btn-danger:hover {
background: rgba(220, 53, 69, 0.2);
}
.btn-warning {
background: rgba(255, 193, 7, 0.1);
color: #ffc107;
border-color: rgba(255, 193, 7, 0.3);
}
.btn-warning:hover {
background: rgba(255, 193, 7, 0.2);
}
/* ==== 模态框 ==== */
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 1000;
backdrop-filter: blur(5px);
}
.modal-content {
background: #ffffff;
margin: 5% auto;
padding: 30px;
border-radius: 15px;
width: 80%;
max-width: 800px;
max-height: 80vh;
overflow-y: auto;
box-shadow: 0 10px 30px rgba(0, 75, 150, 0.2);
}
.modal h2 {
color: #1a4b8c;
margin-bottom: 20px;
font-size: 20px;
border-bottom: 1px solid #e1e9f5;
padding-bottom: 10px;
}
.close {
color: #4a6fa5;
float: right;
font-size: 28px;
font-weight: bold;
cursor: pointer;
margin-top: -10px;
transition: all 0.3s ease;
}
.close:hover {
color: #2a7de1;
}
/* ==== 滚动条样式 ==== */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: #f5f9ff;
border-radius: 4px;
}
::-webkit-scrollbar-thumb {
background: #d1e0f5;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #a8c0e0;
}
/* 设备详情内容样式 */
.device-details-content {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 15px;
}
.device-details-content .detail-item {
margin-bottom: 15px;
}
.device-details-content .detail-label {
color: #4a6fa5;
font-size: 14px;
font-weight: 500;
margin-bottom: 5px;
}
.device-details-content .detail-value {
color: #1a4b8c;
font-size: 16px;
padding: 8px;
background: #f5f9ff;
border-radius: 6px;
border: 1px solid #e1e9f5;
}
/* 地图控制按钮样式 */
.map-control-btn {
background: rgba(255, 255, 255, 0.9);
border: 1px solid #d1e0f5;
color: #4a6fa5;
border-radius: 4px;
padding: 6px 10px;
cursor: pointer;
display: flex;
align-items: center;
gap: 5px;
font-size: 12px;
transition: all 0.3s;
}
.map-control-btn:hover {
background: rgba(42, 125, 225, 0.1);
color: #1a4b8c;
}
.map-control-btn.active {
background: rgba(42, 125, 225, 0.8);
color: #fff;
border-color: #2a7de1;
}
.map-controls {
position: absolute;
top: 160px;
right: 40px;
z-index: 1000;
display: flex;
flex-direction: column;
gap: 5px;
}
.map-footer {
display: flex;
justify-content: flex-end;
gap: 10px;
margin-top: 15px;
padding-top: 15px;
border-top: 1px solid #e1e9f5;
}
/* 统一按钮样式 */
.btn {
padding: 8px 16px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
transition: all 0.3s;
display: inline-flex;
align-items: center;
gap: 8px;
}
/* 采购表单特定样式 */
#orderPartForm input[readonly] {
background-color: #f5f9ff;
color: #4a6fa5;
border: 1px solid #d1e0f5;
}
#orderPartForm input[type="number"] {
background-color: #ffffff;
color: #1a4b8c;
}
#orderTotalPrice {
font-weight: bold;
color: #1a4b8c;
}
/* 审批表单特定样式 */
#approveDisposalForm input[type="radio"] {
margin: 0;
width: 16px;
height: 16px;
}
#approveDisposalForm .detail-value select,
#approveDisposalForm .detail-value textarea {
background: #f5f9ff;
border: 1px solid #d1e0f5;
border-radius: 6px;
padding: 8px;
color: #1a4b8c;
font-size: 14px;
width: 100%;
box-sizing: border-box;
}
#approveDisposalForm .detail-value textarea {
min-height: 80px;
resize: vertical;
}
#approveDisposalForm input:disabled,
#approveDisposalForm select:disabled,
#approveDisposalForm textarea:disabled {
background-color: #f0f0f0;
color: #666;
}
/* 执行维护表单特定样式 */
#executeMaintenanceForm input[type="datetime-local"],
#executeMaintenanceForm select,
#executeMaintenanceForm textarea {
background: #f5f9ff;
border: 1px solid #d1e0f5;
border-radius: 6px;
padding: 8px;
color: #1a4b8c;
font-size: 14px;
width: 100%;
box-sizing: border-box;
}
#executeMaintenanceForm textarea {
min-height: 100px;
resize: vertical;
}
#usedPartsTable {
width: 100%;
border: 1px solid #e1e9f5;
border-radius: 6px;
overflow: hidden;
}
#usedPartsTable th {
background-color: #f5f9ff;
color: #1a4b8c;
font-weight: 500;
font-size: 13px;
}
#usedPartsTable td {
color: #4a6fa5;
font-size: 13px;
}
#photoPreview img {
border: 1px solid #e1e9f5;
transition: all 0.3s;
}
#photoPreview img:hover {
transform: scale(1.05);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
/* 处理维修表单特定样式 */
#processRepairForm input[type="datetime-local"],
#processRepairForm select,
#processRepairForm textarea {
background: #f5f9ff;
border: 1px solid #d1e0f5;
border-radius: 6px;
padding: 8px;
color: #1a4b8c;
font-size: 14px;
width: 100%;
box-sizing: border-box;
}
#processRepairForm textarea {
min-height: 80px;
resize: vertical;
}
#repairActionsTable,
#repairPartsTable {
width: 100%;
border: 1px solid #e1e9f5;
border-radius: 6px;
overflow: hidden;
}
#repairActionsTable th,
#repairPartsTable th {
background-color: #f5f9ff;
color: #1a4b8c;
font-weight: 500;
font-size: 13px;
}
#repairActionsTable td,
#repairPartsTable td {
color: #4a6fa5;
font-size: 13px;
}
#repairPhotoPreview img {
border: 1px solid #e1e9f5;
transition: all 0.3s;
}
#repairPhotoPreview img:hover {
transform: scale(1.05);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
</style>
</head>
<body>
<div class="main-container">
<!-- 左侧内容区域 -->
<div class="content-area">
<div class="device-header">
<h1 class="device-title">设备管理</h1>
<div class="device-actions">
<button class="action-btn" onclick="openDeviceModal()">📝 新增设备</button>
<button class="action-btn" onclick="openMaintenanceModal()">🔧 维护计划</button>
<button class="action-btn" onclick="exportReport()">📊 导出报表</button>
<button class="action-btn" onclick="location.href='index.html'">
<i class="fas fa-home-alt" style="color: orange;margin-right: 5px;"></i>
回到首页
</button>
</div>
</div>
<div class="device-tabs">
<button class="tab-btn active" onclick="switchTab('archive')">设备档案</button>
<button class="tab-btn" onclick="switchTab('monitor')">实时监控</button>
<button class="tab-btn" onclick="switchTab('maintenance')">维护保养</button>
<button class="tab-btn" onclick="switchTab('repair')">故障维修</button>
<button class="tab-btn" onclick="switchTab('parts')">备件管理</button>
<button class="tab-btn" onclick="switchTab('disposal')">报废处置</button>
<button class="tab-btn" onclick="switchTab('analysis')">统计分析</button>
</div>
<!-- 设备档案 -->
<div id="archive" class="tab-content active">
<div class="device-card">
<div class="card-title">
<i class="fas fa-archive"></i>
设备档案管理
</div>
<div class="form-grid">
<div class="form-group">
<label>设备类型</label>
<select id="deviceTypeFilter">
<option value="all">全部类型</option>
<option value="ship">打捞无人船</option>
<option value="drone">巡查无人机</option>
<option value="camera">智能摄像头</option>
<option value="truck">密闭转运车</option>
</select>
</div>
<div class="form-group">
<label>设备状态</label>
<select id="deviceStatusFilter">
<option value="all">全部状态</option>
<option value="online">在线</option>
<option value="offline">离线</option>
<option value="maintenance">维护中</option>
<option value="fault">故障</option>
</select>
</div>
<div class="form-group">
<label>所属区域</label>
<select id="deviceAreaFilter">
<option value="all">全部区域</option>
<option value="yuelu">岳麓区沿岸</option>
<option value="tianxin">天心区沿岸</option>
<option value="kaifu">开福区沿岸</option>
<option value="yuhua">雨花区沿岸</option>
</select>
</div>
<div class="form-group">
<label>搜索设备</label>
<input type="text" id="deviceSearch" placeholder="输入设备编号或名称">
</div>
</div>
<div class="device-grid" id="deviceArchiveGrid">
<!-- 设备档案卡片将通过JS动态加载 -->
</div>
</div>
</div>
<!-- 实时监控 -->
<div id="monitor" class="tab-content">
<div class="device-card">
<div class="card-title">
<i class="fas fa-desktop"></i>
设备实时状态监控
</div>
<table class="device-table">
<thead>
<tr>
<th>设备编号</th>
<th>设备名称</th>
<th>类型</th>
<th>当前位置</th>
<th>电量/状态</th>
<th>在线状态</th>
<th>最后更新</th>
<th>操作</th>
</tr>
</thead>
<tbody id="monitorTableBody">
<!-- 监控数据将通过JS动态加载 -->
</tbody>
</table>
<!-- 分页控件容器 -->
<div id="monitorPagination"
style="display: flex; justify-content: flex-end; align-items: center; gap: 8px; margin: 16px 0 0 0;">
</div>
</div>
</div>
<!-- 维护保养 -->
<div id="maintenance" class="tab-content">
<div class="device-card">
<div class="card-title">
<i class="fas fa-tools"></i>
维护保养计划
</div>
<table class="device-table">
<thead>
<tr>
<th>计划编号</th>
<th>设备编号</th>
<th>设备名称</th>
<th>保养类型</th>
<th>计划时间</th>
<th>负责人</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody id="maintenanceTableBody">
<!-- 维护数据将通过JS动态加载 -->
</tbody>
</table>
</div>
</div>
<!-- 故障维修 -->
<div id="repair" class="tab-content">
<div class="device-card">
<div class="card-title">
<i class="fas fa-wrench"></i>
故障维修管理
</div>
<table class="device-table">
<thead>
<tr>
<th>维修单号</th>
<th>设备编号</th>
<th>故障描述</th>
<th>报修人</th>
<th>维修人员</th>
<th>紧急程度</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody id="repairTableBody">
<!-- 维修数据将通过JS动态加载 -->
</tbody>
</table>
</div>
</div>
<!-- 备件管理 -->
<div id="parts" class="tab-content">
<div class="device-card">
<div class="card-title">
<i class="fas fa-boxes"></i>
备件库存管理
</div>
<table class="device-table">
<thead>
<tr>
<th>备件编号</th>
<th>备件名称</th>
<th>适用设备</th>
<th>当前库存</th>
<th>最低库存</th>
<th>单价</th>
<th>供应商</th>
<th>操作</th>
</tr>
</thead>
<tbody id="partsTableBody">
<!-- 备件数据将通过JS动态加载 -->
</tbody>
</table>
</div>
</div>
<!-- 报废处置 -->
<div id="disposal" class="tab-content">
<div class="device-card">
<div class="card-title">
<i class="fas fa-trash-alt"></i>
设备报废处置
</div>
<table class="device-table">
<thead>
<tr>
<th>申请编号</th>
<th>设备编号</th>
<th>设备名称</th>
<th>报废原因</th>
<th>申请人</th>
<th>申请时间</th>
<th>审批状态</th>
<th>操作</th>
</tr>
</thead>
<tbody id="disposalTableBody">
<!-- 报废数据将通过JS动态加载 -->
</tbody>
</table>
</div>
</div>
<!-- 统计分析 -->
<div id="analysis" class="tab-content">
<div class="device-card">
<div class="card-title">
<i class="fas fa-chart-bar"></i>
设备效能分析
</div>
<div class="form-grid">
<div class="form-group">
<label>统计周期</label>
<select id="analysisPeriod">
<option value="week">本周</option>
<option value="month">本月</option>
<option value="quarter">本季度</option>
<option value="year">本年度</option>
</select>
</div>
<div class="form-group">
<label>分析维度</label>
<select id="analysisDimension">
<option value="type">按设备类型</option>
<option value="area">按区域分布</option>
<option value="usage">按使用频率</option>
</select>
</div>
</div>
<div class="stats-grid">
<div class="stat-item">
<span class="stat-value" id="totalDevices">45</span>
<div class="stat-label">设备总数</div>
</div>
<div class="stat-item">
<span class="stat-value" id="onlineRate">87.2%</span>
<div class="stat-label">在线率</div>
</div>
<div class="stat-item">
<span class="stat-value" id="utilizationRate">73.5%</span>
<div class="stat-label">利用率</div>
</div>
<div class="stat-item">
<span class="stat-value" id="faultRate">2.3%</span>
<div class="stat-label">故障率</div>
</div>
</div>
<div class="chart-container" style="height: 400px;">
<canvas id="analysisChart"></canvas>
</div>
</div>
</div>
</div>
<!-- 右侧侧边栏 -->
<div class="sidebar-area">
<div class="sidebar-section">
<div class="sidebar-title">
<i class="fas fa-tachometer-alt"></i>
设备概览
</div>
<div class="stats-grid">
<div class="stat-item">
<span class="stat-value">39</span>
<div class="stat-label">在线设备</div>
</div>
<div class="stat-item">
<span class="stat-value">6</span>
<div class="stat-label">离线设备</div>
</div>
<div class="stat-item">
<span class="stat-value">3</span>
<div class="stat-label">维护中</div>
</div>
<div class="stat-item">
<span class="stat-value">2</span>
<div class="stat-label">故障设备</div>
</div>
</div>
</div>
<div class="sidebar-section">
<div class="sidebar-title">
<i class="fas fa-exclamation-triangle"></i>
设备告警
</div>
<div class="alert-list" id="deviceAlerts">
<!-- 告警信息列表 -->
</div>
</div>
<div class="sidebar-section">
<div class="sidebar-title">
<i class="fas fa-chart-pie"></i>
设备分布
</div>
<div class="chart-container">
<canvas id="distributionChart"></canvas>
</div>
</div>
<div class="sidebar-section">
<div class="sidebar-title">
<i class="fas fa-clock"></i>
维护提醒
</div>
<div class="alert-list" id="maintenanceReminders">
<!-- 维护提醒列表 -->
</div>
</div>
</div>
</div>
<!-- 新增设备模态框 -->
<div id="deviceModal" class="modal">
<div class="modal-content">
<span class="close" onclick="closeDeviceModal()">&times;</span>
<h2>新增设备档案</h2>
<form id="deviceForm">
<div class="form-grid">
<div class="form-group">
<label>设备编号</label>
<input type="text" name="deviceId" placeholder="如UC-2025001" required>
</div>
<div class="form-group">
<label>设备名称</label>
<input type="text" name="deviceName" placeholder="如垃圾打捞无人船A01" required>
</div>
<div class="form-group">
<label>设备类型</label>
<select name="deviceType" required>
<option value="">请选择类型</option>
<option value="ship">打捞无人船</option>
<option value="drone">巡查无人机</option>
<option value="camera">智能摄像头</option>
<option value="truck">密闭转运车</option>
</select>
</div>
<div class="form-group">
<label>型号规格</label>
<input type="text" name="model" placeholder="设备型号">
</div>
<div class="form-group">
<label>生产厂商</label>
<input type="text" name="manufacturer" placeholder="厂商名称">
</div>
<div class="form-group">
<label>采购日期</label>
<input type="date" name="purchaseDate" required>
</div>
<div class="form-group">
<label>所属区域</label>
<select name="area" required>
<option value="">请选择区域</option>
<option value="yuelu">岳麓区沿岸</option>
<option value="tianxin">天心区沿岸</option>
<option value="kaifu">开福区沿岸</option>
<option value="yuhua">雨花区沿岸</option>
</select>
</div>
<div class="form-group">
<label>管理责任人</label>
<select name="manager" required>
<option value="">请选择责任人</option>
<option value="zhang">张三</option>
<option value="li">李四</option>
<option value="wang">王五</option>
<option value="zhao">赵六</option>
</select>
</div>
</div>
<div class="form-group">
<label>技术参数</label>
<textarea name="specifications" rows="4" placeholder="请输入设备的技术参数和规格"></textarea>
</div>
<div class="form-group">
<label>备注信息</label>
<textarea name="remarks" rows="3" placeholder="其他说明信息"></textarea>
</div>
<div style="text-align: right; margin-top: 20px;">
<button type="button" class="btn" onclick="closeDeviceModal()">取消</button>
<button type="submit" class="btn btn-primary">保存设备</button>
</div>
</form>
</div>
</div>
<!-- 维护计划模态框 -->
<div id="maintenanceModal" class="modal">
<div class="modal-content">
<span class="close" onclick="closeMaintenanceModal()">&times;</span>
<h2>制定维护计划</h2>
<form id="maintenanceForm">
<div class="form-grid">
<div class="form-group">
<label>选择设备</label>
<select name="deviceId" required>
<option value="">请选择设备</option>
<option value="UC-2025001">UC-2025001 - 垃圾打捞无人船A01</option>
<option value="UD-2025001">UD-2025001 - 巡查无人机B01</option>
<option value="IC-2025001">IC-2025001 - 智能摄像头C01</option>
</select>
</div>
<div class="form-group">
<label>保养类型</label>
<select name="maintenanceType" required>
<option value="">请选择类型</option>
<option value="routine">例行保养</option>
<option value="periodic">周期保养</option>
<option value="condition">条件保养</option>
<option value="emergency">紧急保养</option>
</select>
</div>
<div class="form-group">
<label>计划时间</label>
<input type="datetime-local" name="scheduledTime" required>
</div>
<div class="form-group">
<label>负责人</label>
<select name="assignee" required>
<option value="">请选择负责人</option>
<option value="zhang">张三</option>
<option value="li">李四</option>
<option value="wang">王五</option>
<option value="zhao">赵六</option>
</select>
</div>
</div>
<div class="form-group">
<label>保养内容</label>
<textarea name="content" rows="4" placeholder="请描述具体的保养项目和要求"></textarea>
</div>
<div class="form-group">
<label>所需备件</label>
<textarea name="parts" rows="3" placeholder="列出所需的备件和耗材"></textarea>
</div>
<div style="text-align: right; margin-top: 20px;">
<button type="button" class="btn" onclick="closeMaintenanceModal()">取消</button>
<button type="submit" class="btn btn-primary">创建计划</button>
</div>
</form>
</div>
</div>
<!-- 查看设备模态框 -->
<div id="viewDeviceModal" class="modal">
<div class="modal-content">
<span class="close" onclick="closeViewDeviceModal()">&times;</span>
<h2>设备详情</h2>
<div id="deviceDetailsContent" class="device-details-content">
<!-- 内容将通过JS动态加载 -->
</div>
<div style="text-align: right; margin-top: 20px;">
<button type="button" class="btn" onclick="closeViewDeviceModal()">关闭</button>
</div>
</div>
</div>
<!-- 编辑设备模态框 -->
<div id="editDeviceModal" class="modal">
<div class="modal-content">
<span class="close" onclick="closeEditDeviceModal()">&times;</span>
<h2>编辑设备</h2>
<form id="editDeviceForm">
<input type="hidden" id="editDeviceId" name="deviceId">
<div class="form-grid">
<div class="form-group">
<label>设备名称</label>
<input type="text" id="editDeviceName" name="deviceName" required>
</div>
<div class="form-group">
<label>设备类型</label>
<select id="editDeviceType" name="deviceType" required>
<option value="ship">打捞无人船</option>
<option value="drone">巡查无人机</option>
<option value="camera">智能摄像头</option>
<option value="truck">密闭转运车</option>
</select>
</div>
<div class="form-group">
<label>所属区域</label>
<select id="editDeviceArea" name="area" required>
<option value="yuelu">岳麓区沿岸</option>
<option value="tianxin">天心区沿岸</option>
<option value="kaifu">开福区沿岸</option>
<option value="yuhua">雨花区沿岸</option>
</select>
</div>
<div class="form-group">
<label>管理责任人</label>
<select id="editDeviceManager" name="manager" required>
<option value="zhang">张三</option>
<option value="li">李四</option>
<option value="wang">王五</option>
<option value="zhao">赵六</option>
</select>
</div>
<div class="form-group">
<label>设备状态</label>
<select id="editDeviceStatus" name="status" required>
<option value="online">在线</option>
<option value="offline">离线</option>
<option value="maintenance">维护中</option>
<option value="fault">故障</option>
</select>
</div>
</div>
<div style="text-align: right; margin-top: 20px;">
<button type="button" class="btn" onclick="closeEditDeviceModal()">取消</button>
<button type="submit" class="btn btn-primary">保存更改</button>
</div>
</form>
</div>
</div>
<!-- 设备定位模态框 -->
<div id="locationModal" class="modal">
<div class="modal-content" style="width: 90%; max-width: 1000px;position: relative;">
<span class="close" onclick="closeLocationModal()">&times;</span>
<h2><i class="fas fa-map-marker-alt"></i> 设备实时位置</h2>
<div class="map-header">
<h4>设备位置:
<span id="deviceLocationTitle"></span>
<span style="float: right;">坐标: <span id="deviceCoordinates">112.955, 28.195</span>
</span>
</h4>
<div class="map-controls">
<button class="map-control-btn active" data-view="satellite"
onclick="switchDeviceMapType('satellite')">卫星图</button>
<button class="map-control-btn" data-view="street"
onclick="switchDeviceMapType('street')">街道图</button>
<button class="map-control-btn" data-view="terrain"
onclick="switchDeviceMapType('terrain')">地形图</button>
</div>
</div>
<div id="deviceMap" class="tracking-map" style="height: 500px;"></div>
<div class="map-footer">
<!-- <div class="coordinates-display">
坐标: <span id="deviceCoordinates">112.955, 28.195</span>
</div> -->
<button class="btn" onclick="closeLocationModal()">关闭</button>
</div>
</div>
</div>
<!-- 查看设备详情模态框 -->
<div id="viewDetailsModal" class="modal">
<div class="modal-content">
<span class="close" onclick="closeViewDetailsModal()">&times;</span>
<h2>设备详情</h2>
<div id="deviceDetailsContents" class="device-details-content">
<!-- 内容将通过JS动态加载 -->
</div>
<div style="text-align: right; margin-top: 20px;">
<button type="button" class="btn" onclick="closeViewDetailsModal()">关闭</button>
</div>
</div>
</div>
<!-- 查看维护计划详情模态框 -->
<div id="viewMaintenanceModal" class="modal">
<div class="modal-content">
<span class="close" onclick="closeViewMaintenanceModal()">&times;</span>
<h2>维护保养计划详情</h2>
<div id="maintenanceDetailsContent" class="device-details-content">
<!-- 内容将通过JS动态加载 -->
</div>
<div style="text-align: right; margin-top: 20px;">
<button type="button" class="btn" onclick="closeViewMaintenanceModal()">关闭</button>
</div>
</div>
</div>
<!-- 执行维护计划模态框 -->
<div id="executeMaintenanceModal" class="modal">
<div class="modal-content">
<span class="close" onclick="closeExecuteMaintenanceModal()">&times;</span>
<h2>执行维护保养</h2>
<form id="executeMaintenanceForm">
<input type="hidden" id="executePlanId" name="planId">
<div class="device-details-content">
<div class="detail-item">
<div class="detail-label">计划编号</div>
<div class="detail-value" id="executePlanNo"></div>
</div>
<div class="detail-item">
<div class="detail-label">设备名称</div>
<div class="detail-value" id="executeDeviceName"></div>
</div>
<div class="detail-item">
<div class="detail-label">保养类型</div>
<div class="detail-value" id="executeMaintenanceType"></div>
</div>
<div class="detail-item">
<div class="detail-label">计划时间</div>
<div class="detail-value" id="executeScheduledTime"></div>
</div>
<div class="detail-item">
<div class="detail-label">负责人</div>
<div class="detail-value" id="executeAssignee"></div>
</div>
<div class="detail-item" style="grid-column: 1 / -1;">
<div class="detail-label">实际执行时间</div>
<div class="detail-value">
<input type="datetime-local" id="executeActualTime" name="actualTime" required
style="width: 100%;">
</div>
</div>
<div class="detail-item" style="grid-column: 1 / -1;">
<div class="detail-label">执行人员</div>
<div class="detail-value">
<select id="executeOperator" name="operator" required style="width: 100%;">
<option value="">请选择执行人员</option>
<option value="tech1">技术员张三</option>
<option value="tech2">技术员李四</option>
<option value="tech3">技术员王五</option>
</select>
</div>
</div>
<div class="detail-item" style="grid-column: 1 / -1;">
<div class="detail-label">使用备件</div>
<div class="detail-value">
<div style="display: flex; gap: 10px; margin-bottom: 10px;">
<select id="executePartSelect" style="flex: 1;">
<option value="">选择备件</option>
<option value="P001">P001 - 无人船专用电池</option>
<option value="P002">P002 - 无人机螺旋桨</option>
<option value="P003">P003 - 摄像头镜头</option>
<option value="P004">P004 - 转运车轮胎</option>
</select>
<input type="number" id="executePartQuantity" min="1" value="1" style="width: 80px;">
<button type="button" class="btn btn-primary" onclick="addUsedPart()"
style="width: 80px;">添加</button>
</div>
<table id="usedPartsTable"
style="width: 100%; border-collapse: collapse; margin-top: 10px;">
<thead>
<tr style="background-color: #f5f9ff;">
<th style="padding: 8px; text-align: left; border-bottom: 1px solid #e1e9f5;">
备件编号</th>
<th style="padding: 8px; text-align: left; border-bottom: 1px solid #e1e9f5;">
备件名称</th>
<th style="padding: 8px; text-align: right; border-bottom: 1px solid #e1e9f5;">
数量</th>
<th style="padding: 8px; text-align: center; border-bottom: 1px solid #e1e9f5;">
操作</th>
</tr>
</thead>
<tbody id="usedPartsList">
<!-- 动态添加使用的备件 -->
</tbody>
</table>
</div>
</div>
<div class="detail-item" style="grid-column: 1 / -1;">
<div class="detail-label">执行情况</div>
<div class="detail-value">
<textarea id="executeResult" name="result" rows="4" style="width: 100%;"
placeholder="请描述维护保养的具体执行情况和发现的问题" required></textarea>
</div>
</div>
<div class="detail-item" style="grid-column: 1 / -1;">
<div class="detail-label">设备状态</div>
<div class="detail-value">
<select id="executeDeviceStatus" name="deviceStatus" required style="width: 100%;">
<option value="">请选择维护后设备状态</option>
<option value="online">正常在线</option>
<option value="maintenance">需进一步维护</option>
<option value="fault">发现新故障</option>
</select>
</div>
</div>
<div class="detail-item" style="grid-column: 1 / -1;">
<div class="detail-label">上传照片</div>
<div class="detail-value">
<input type="file" id="executePhotos" name="photos" accept="image/*" multiple
style="width: 100%;">
<div id="photoPreview" style="display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px;">
</div>
</div>
</div>
</div>
<div style="text-align: right; margin-top: 20px;">
<button type="button" class="btn" onclick="closeExecuteMaintenanceModal()">取消</button>
<button type="submit" class="btn btn-primary">提交执行结果</button>
</div>
</form>
</div>
</div>
<!-- 查看故障维修详情模态框 -->
<div id="viewRepairModal" class="modal">
<div class="modal-content">
<span class="close" onclick="closeViewRepairModal()">&times;</span>
<h2>故障维修详情</h2>
<div id="repairDetailsContent" class="device-details-content">
<!-- 内容将通过JS动态加载 -->
</div>
<div style="text-align: right; margin-top: 20px;">
<button type="button" class="btn" onclick="closeViewRepairModal()">关闭</button>
</div>
</div>
</div>
<!-- 处理故障维修模态框 -->
<div id="processRepairModal" class="modal">
<div class="modal-content">
<span class="close" onclick="closeProcessRepairModal()">&times;</span>
<h2>故障维修处理</h2>
<form id="processRepairForm">
<input type="hidden" id="processRepairId" name="repairId">
<div class="device-details-content">
<div class="detail-item">
<div class="detail-label">维修单号</div>
<div class="detail-value" id="processRepairNo"></div>
</div>
<div class="detail-item">
<div class="detail-label">设备名称</div>
<div class="detail-value" id="processDeviceName"></div>
</div>
<div class="detail-item">
<div class="detail-label">故障描述</div>
<div class="detail-value" id="processFaultDesc"></div>
</div>
<div class="detail-item">
<div class="detail-label">报修人</div>
<div class="detail-value" id="processReporter"></div>
</div>
<div class="detail-item">
<div class="detail-label">紧急程度</div>
<div class="detail-value" id="processPriority"></div>
</div>
<div class="detail-item" style="grid-column: 1 / -1;">
<div class="detail-label">维修人员</div>
<div class="detail-value">
<select id="repairTechnician" name="technician" required style="width: 100%;">
<option value="">请选择维修人员</option>
<option value="tech1">高级技师-张三</option>
<option value="tech2">技师-李四</option>
<option value="tech3">技术员-王五</option>
</select>
</div>
</div>
<div class="detail-item" style="grid-column: 1 / -1;">
<div class="detail-label">开始时间</div>
<div class="detail-value">
<input type="datetime-local" id="repairStartTime" name="startTime" required
style="width: 100%;">
</div>
</div>
<div class="detail-item" style="grid-column: 1 / -1;">
<div class="detail-label">故障诊断</div>
<div class="detail-value">
<textarea id="repairDiagnosis" name="diagnosis" rows="3" style="width: 100%;"
placeholder="请描述故障诊断过程和发现的根本原因" required></textarea>
</div>
</div>
<div class="detail-item" style="grid-column: 1 / -1;">
<div class="detail-label">维修措施</div>
<div class="detail-value">
<div style="display: flex; gap: 10px; margin-bottom: 10px;">
<select id="repairActionSelect" style="flex: 1;">
<option value="">选择维修措施</option>
<option value="replace">更换部件</option>
<option value="repair">修复部件</option>
<option value="adjust">调整参数</option>
<option value="clean">清洁维护</option>
<option value="software">软件修复</option>
</select>
<button type="button" class="btn btn-primary" onclick="addRepairAction()"
style="width: 80px;">添加</button>
</div>
<table id="repairActionsTable"
style="width: 100%; border-collapse: collapse; margin-top: 10px;">
<thead>
<tr style="background-color: #f5f9ff;">
<th style="padding: 8px; text-align: left; border-bottom: 1px solid #e1e9f5;">
措施类型</th>
<th style="padding: 8px; text-align: left; border-bottom: 1px solid #e1e9f5;">
详细说明</th>
<th style="padding: 8px; text-align: center; border-bottom: 1px solid #e1e9f5;">
操作</th>
</tr>
</thead>
<tbody id="repairActionsList">
<!-- 动态添加维修措施 -->
</tbody>
</table>
</div>
</div>
<div class="detail-item" style="grid-column: 1 / -1;">
<div class="detail-label">使用备件</div>
<div class="detail-value">
<div style="display: flex; gap: 10px; margin-bottom: 10px;">
<select id="repairPartSelect" style="flex: 1;">
<option value="">选择备件</option>
<option value="P001">P001 - 无人船专用电池</option>
<option value="P002">P002 - 无人机螺旋桨</option>
<option value="P003">P003 - 摄像头镜头</option>
<option value="P004">P004 - 转运车轮胎</option>
</select>
<input type="number" id="repairPartQuantity" min="1" value="1" style="width: 80px;">
<button type="button" class="btn btn-primary" onclick="addRepairPart()"
style="width: 80px;">添加</button>
</div>
<table id="repairPartsTable"
style="width: 100%; border-collapse: collapse; margin-top: 10px;">
<thead>
<tr style="background-color: #f5f9ff;">
<th style="padding: 8px; text-align: left; border-bottom: 1px solid #e1e9f5;">
备件编号</th>
<th style="padding: 8px; text-align: left; border-bottom: 1px solid #e1e9f5;">
备件名称</th>
<th style="padding: 8px; text-align: right; border-bottom: 1px solid #e1e9f5;">
数量</th>
<th style="padding: 8px; text-align: center; border-bottom: 1px solid #e1e9f5;">
操作</th>
</tr>
</thead>
<tbody id="repairPartsList">
<!-- 动态添加使用的备件 -->
</tbody>
</table>
</div>
</div>
<div class="detail-item" style="grid-column: 1 / -1;">
<div class="detail-label">维修结果</div>
<div class="detail-value">
<select id="repairResult" name="result" required style="width: 100%;">
<option value="">请选择维修结果</option>
<option value="fixed">已修复</option>
<option value="partial">部分修复</option>
<option value="unfixed">未修复</option>
<option value="unrepairable">无法修复</option>
</select>
</div>
</div>
<div class="detail-item" style="grid-column: 1 / -1;">
<div class="detail-label">维修说明</div>
<div class="detail-value">
<textarea id="repairNotes" name="notes" rows="4" style="width: 100%;"
placeholder="请详细描述维修过程和最终结果" required></textarea>
</div>
</div>
<div class="detail-item" style="grid-column: 1 / -1;">
<div class="detail-label">设备状态</div>
<div class="detail-value">
<select id="repairDeviceStatus" name="deviceStatus" required style="width: 100%;">
<option value="">请选择维修后设备状态</option>
<option value="online">正常在线</option>
<option value="limited">功能受限</option>
<option value="maintenance">需进一步维护</option>
<option value="scrapped">建议报废</option>
</select>
</div>
</div>
<div class="detail-item" style="grid-column: 1 / -1;">
<div class="detail-label">上传照片</div>
<div class="detail-value">
<input type="file" id="repairPhotos" name="photos" accept="image/*" multiple
style="width: 100%;">
<div id="repairPhotoPreview"
style="display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px;"></div>
</div>
</div>
</div>
<div style="text-align: right; margin-top: 20px;">
<button type="button" class="btn" onclick="closeProcessRepairModal()">取消</button>
<button type="submit" class="btn btn-primary">提交处理结果</button>
</div>
</form>
</div>
</div>
<!-- 查看备件详情模态框 -->
<div id="viewPartModal" class="modal">
<div class="modal-content">
<span class="close" onclick="closeViewPartModal()">&times;</span>
<h2>备件详情</h2>
<div id="partDetailsContent" class="device-details-content">
<!-- 内容将通过JS动态加载 -->
</div>
<div style="text-align: right; margin-top: 20px;">
<button type="button" class="btn" onclick="closeViewPartModal()">关闭</button>
</div>
</div>
</div>
<!-- 采购备件模态框 -->
<div id="orderPartModal" class="modal">
<div class="modal-content">
<span class="close" onclick="closeOrderPartModal()">&times;</span>
<h2>备件采购</h2>
<form id="orderPartForm">
<input type="hidden" id="orderPartId" name="partId">
<div class="form-grid">
<div class="form-group">
<label>备件名称</label>
<input type="text" id="orderPartName" readonly>
</div>
<div class="form-group">
<label>适用设备</label>
<input type="text" id="orderPartDevice" readonly>
</div>
<div class="form-group">
<label>当前库存</label>
<input type="text" id="orderCurrentStock" readonly>
</div>
<div class="form-group">
<label>最低库存</label>
<input type="text" id="orderMinStock" readonly>
</div>
<div class="form-group">
<label>采购数量</label>
<input type="number" id="orderQuantity" name="quantity" min="1" value="1" required>
</div>
<div class="form-group">
<label>单价</label>
<input type="text" id="orderUnitPrice" readonly>
</div>
<div class="form-group">
<label>总价</label>
<input type="text" id="orderTotalPrice" readonly>
</div>
<div class="form-group">
<label>供应商</label>
<input type="text" id="orderSupplier" readonly>
</div>
<div class="form-group">
<label>采购人</label>
<select id="orderPurchaser" name="purchaser" required>
<option value="">请选择采购人</option>
<option value="zhang">张三</option>
<option value="li">李四</option>
<option value="wang">王五</option>
</select>
</div>
<div class="form-group">
<label>预计到货时间</label>
<input type="date" id="orderExpectedDate" name="expectedDate" required>
</div>
</div>
<div class="form-group">
<label>采购备注</label>
<textarea id="orderNotes" name="notes" rows="3" placeholder="请输入采购备注信息"></textarea>
</div>
<div style="text-align: right; margin-top: 20px;">
<button type="button" class="btn" onclick="closeOrderPartModal()">取消</button>
<button type="submit" class="btn btn-primary">提交采购</button>
</div>
</form>
</div>
</div>
<!-- 查看报废设备详情模态框 -->
<div id="viewDisposalModal" class="modal">
<div class="modal-content">
<span class="close" onclick="closeViewDisposalModal()">&times;</span>
<h2>报废处置详情</h2>
<div id="disposalDetailsContent" class="device-details-content">
<!-- 内容将通过JS动态加载 -->
</div>
<div style="text-align: right; margin-top: 20px;">
<button type="button" class="btn" onclick="closeViewDisposalModal()">关闭</button>
</div>
</div>
</div>
<!-- 审批报废设备模态框 -->
<div id="approveDisposalModal" class="modal">
<div class="modal-content">
<span class="close" onclick="closeApproveDisposalModal()">&times;</span>
<h2>报废处置审批</h2>
<form id="approveDisposalForm">
<input type="hidden" id="approveDisposalId" name="disposalId">
<div class="device-details-content">
<div class="detail-item">
<div class="detail-label">申请编号</div>
<div class="detail-value" id="approveAppId"></div>
</div>
<div class="detail-item">
<div class="detail-label">设备名称</div>
<div class="detail-value" id="approveDeviceName"></div>
</div>
<div class="detail-item">
<div class="detail-label">报废原因</div>
<div class="detail-value" id="approveReason"></div>
</div>
<div class="detail-item">
<div class="detail-label">申请人</div>
<div class="detail-value" id="approveApplicant"></div>
</div>
<div class="detail-item">
<div class="detail-label">申请时间</div>
<div class="detail-value" id="approveApplyTime"></div>
</div>
<div class="detail-item">
<div class="detail-label">技术评估</div>
<div class="detail-value" id="approveEvaluation"></div>
</div>
<div class="detail-item" style="grid-column: 1 / -1;">
<div class="detail-label">审批结果</div>
<div class="detail-value">
<div style="display: flex; gap: 15px;">
<label style="display: flex; align-items: center;">
<input type="radio" name="approvalResult" value="approved" required>
<span style="margin-left: 5px;">同意报废</span>
</label>
<label style="display: flex; align-items: center;">
<input type="radio" name="approvalResult" value="rejected" required>
<span style="margin-left: 5px;">驳回申请</span>
</label>
</div>
</div>
</div>
<div class="detail-item" style="grid-column: 1 / -1;">
<div class="detail-label">处置方式</div>
<div class="detail-value">
<select id="disposalMethod" name="disposalMethod" style="width: 100%;">
<option value="">请选择处置方式</option>
<option value="环保拆解回收">环保拆解回收</option>
<option value="部件拆解后分类处理">部件拆解后分类处理</option>
<option value="整机拍卖">整机拍卖</option>
<option value="捐赠教育机构">捐赠教育机构</option>
<option value="其他">其他</option>
</select>
</div>
</div>
<div class="detail-item" style="grid-column: 1 / -1;">
<div class="detail-label">审批意见</div>
<div class="detail-value">
<textarea id="approvalComments" name="approvalComments" rows="3" style="width: 100%;"
placeholder="请输入审批意见" required></textarea>
</div>
</div>
<div class="detail-item" style="grid-column: 1 / -1;">
<div class="detail-label">审批人</div>
<div class="detail-value">
<select id="approver" name="approver" required style="width: 100%;">
<option value="">请选择审批人</option>
<option value="manager1">张经理</option>
<option value="manager2">李总监</option>
<option value="manager3">王总</option>
</select>
</div>
</div>
</div>
<div style="text-align: right; margin-top: 20px;">
<button type="button" class="btn" onclick="closeApproveDisposalModal()">取消</button>
<button type="submit" class="btn btn-primary">提交审批</button>
</div>
</form>
</div>
</div>
<script src="chart.js"></script>
<script>
// 标签页切换
function switchTab(tabName) {
// 隐藏所有标签页内容
document.querySelectorAll('.tab-content').forEach(content => {
content.classList.remove('active');
});
// 移除所有标签按钮的激活状态
document.querySelectorAll('.tab-btn').forEach(btn => {
btn.classList.remove('active');
});
// 显示选中的标签页内容
document.getElementById(tabName).classList.add('active');
// 激活选中的标签按钮
event.target.classList.add('active');
// 根据标签页加载对应数据
switch (tabName) {
case 'archive':
loadDeviceArchive();
break;
case 'monitor':
loadDeviceMonitor();
break;
case 'maintenance':
loadMaintenanceData();
break;
case 'repair':
loadRepairData();
break;
case 'parts':
loadPartsData();
break;
case 'disposal':
loadDisposalData();
break;
case 'analysis':
loadAnalysisData();
break;
}
}
// 加载设备档案数据
function loadDeviceArchive() {
const deviceGrid = document.getElementById('deviceArchiveGrid');
if (!deviceGrid) return;
const statusMap = {
'online': { text: '在线', class: 'status-online' },
'offline': { text: '离线', class: 'status-offline' },
'maintenance': { text: '维护中', class: 'status-maintenance' },
'fault': { text: '故障', class: 'status-fault' }
};
deviceGrid.innerHTML = devices.map(device => `
<div class="device-item">
<div class="device-info">
<div class="device-icon">${device.icon}</div>
<div class="device-details">
<h4>${device.name}</h4>
<p>编号:${device.id}</p>
</div>
</div>
<div class="device-params">
<div class="param-item">
<span class="param-value">${device.battery}</span>
<div class="param-label">电量/状态</div>
</div>
<div class="param-item">
<span class="param-value">${device.workTime}</span>
<div class="param-label">工作时长</div>
</div>
<div class="param-item">
<span class="param-value">${device.area}</span>
<div class="param-label">所属区域</div>
</div>
<div class="param-item">
<span class="param-value">${device.manager}</span>
<div class="param-label">负责人</div>
</div>
</div>
<div style="display: flex; justify-content: space-between; align-items: center;">
<span class="status-badge ${statusMap[device.status].class}">${statusMap[device.status].text}</span>
<div>
<button class="btn btn-primary" onclick="viewDevice('${device.id}')">查看</button>
<button class="btn btn-success" onclick="editDevice('${device.id}')">编辑</button>
</div>
</div>
</div>
`).join('');
}
// 分页相关变量
const MONITOR_PAGE_SIZE = 5;
let currentMonitorPage = 1;
let monitorData = [
{ id: 'UC-2025001', name: '垃圾打捞无人船A01', type: '打捞无人船', location: '橘子洲头', battery: '85%', status: 'online', lastUpdate: '2024-01-15 14:30' },
{ id: 'UD-2025001', name: '巡查无人机B01', type: '巡查无人机', location: '湘江大桥段', battery: '0%', status: 'offline', lastUpdate: '2024-01-15 12:15' },
{ id: 'IC-2025001', name: '智能摄像头C01', type: '智能摄像头', location: '银盆岭大桥', battery: '正常', status: 'online', lastUpdate: '2024-01-15 14:35' },
{ id: 'MT-2025001', name: '密闭转运车D01', type: '密闭转运车', location: '维修车间', battery: '正常', status: 'maintenance', lastUpdate: '2024-01-15 10:00' },
// 添加更多测试数据...
{ id: 'UC-2025002', name: '垃圾打捞无人船A02', type: '打捞无人船', location: '岳麓区沿岸', battery: '78%', status: 'online', lastUpdate: '2024-01-15 15:20' },
{ id: 'UD-2025002', name: '巡查无人机B02', type: '巡查无人机', location: '橘子洲尾', battery: '92%', status: 'online', lastUpdate: '2024-01-15 15:45' }
];
// // 加载设备监控数据
// function loadDeviceMonitor() {
// const monitorTableBody = document.getElementById('monitorTableBody');
// if (!monitorTableBody) return;
// const monitorData = [
// { id: 'UC-2025001', name: '垃圾打捞无人船A01', type: '打捞无人船', location: '橘子洲头', battery: '85%', status: 'online', lastUpdate: '2024-01-15 14:30' },
// { id: 'UD-2025001', name: '巡查无人机B01', type: '巡查无人机', location: '湘江大桥段', battery: '0%', status: 'offline', lastUpdate: '2024-01-15 12:15' },
// { id: 'IC-2025001', name: '智能摄像头C01', type: '智能摄像头', location: '银盆岭大桥', battery: '正常', status: 'online', lastUpdate: '2024-01-15 14:35' },
// { id: 'MT-2025001', name: '密闭转运车D01', type: '密闭转运车', location: '维修车间', battery: '正常', status: 'maintenance', lastUpdate: '2024-01-15 10:00' }
// ];
// const statusMap = {
// 'online': { text: '在线', class: 'status-online' },
// 'offline': { text: '离线', class: 'status-offline' },
// 'maintenance': { text: '维护中', class: 'status-maintenance' }
// };
// monitorTableBody.innerHTML = monitorData.map(device => `
// <tr>
// <td>${device.id}</td>
// <td>${device.name}</td>
// <td>${device.type}</td>
// <td>${device.location}</td>
// <td>${device.battery}</td>
// <td><span class="status-badge ${statusMap[device.status].class}">${statusMap[device.status].text}</span></td>
// <td>${device.lastUpdate}</td>
// <td>
// <button class="btn btn-primary" onclick="locateDevice('${device.id}')">定位</button>
// <button class="btn" onclick="viewDetails('${device.id}')">详情</button>
// </td>
// </tr>
// `).join('');
// }
// 加载监控数据并分页
function loadDeviceMonitor(page = 1) {
const monitorTableBody = document.getElementById('monitorTableBody');
if (!monitorTableBody) return;
const statusMap = {
'online': { text: '在线', class: 'status-online' },
'offline': { text: '离线', class: 'status-offline' },
'maintenance': { text: '维护中', class: 'status-maintenance' }
};
const start = (page - 1) * MONITOR_PAGE_SIZE;
const end = Math.min(start + MONITOR_PAGE_SIZE, monitorData.length);
monitorTableBody.innerHTML = '';
for (let i = start; i < end; i++) {
const device = monitorData[i];
monitorTableBody.innerHTML += `
<tr>
<td>${device.id}</td>
<td>${device.name}</td>
<td>${device.type}</td>
<td>${device.location}</td>
<td>${device.battery}</td>
<td><span class="status-badge ${statusMap[device.status].class}">${statusMap[device.status].text}</span></td>
<td>${device.lastUpdate}</td>
<td>
<button class="btn btn-primary" onclick="locateDevice('${device.id}')">定位</button>
<button class="btn" onclick="viewDetails('${device.id}')">详情</button>
</td>
</tr>
`;
}
renderMonitorPagination(page);
}
// 渲染分页控件
function renderMonitorPagination(page) {
const total = monitorData.length;
const totalPages = Math.ceil(total / MONITOR_PAGE_SIZE);
const container = document.getElementById('monitorPagination');
container.innerHTML = '';
if (totalPages <= 1) return;
// 上一页
const prev = document.createElement('button');
prev.textContent = '上一页';
prev.className = 'btn';
prev.disabled = page === 1;
prev.onclick = () => gotoMonitorPage(page - 1);
container.appendChild(prev);
// 页码
for (let i = 1; i <= totalPages; i++) {
if (i === 1 || i === totalPages || Math.abs(i - page) <= 1) {
const btn = document.createElement('button');
btn.textContent = i;
btn.className = 'btn' + (i === page ? ' btn-primary' : '');
btn.onclick = () => gotoMonitorPage(i);
container.appendChild(btn);
} else if (i === page - 2 || i === page + 2) {
const span = document.createElement('span');
span.textContent = '...';
span.style.margin = '0 4px';
container.appendChild(span);
}
}
// 下一页
const next = document.createElement('button');
next.textContent = '下一页';
next.className = 'btn';
next.disabled = page === totalPages;
next.onclick = () => gotoMonitorPage(page + 1);
container.appendChild(next);
}
function gotoMonitorPage(page) {
currentMonitorPage = page;
loadDeviceMonitor(page);
}
const maintenanceData = [
{ planId: 'M001', deviceId: 'UC-2025001', deviceName: '垃圾打捞无人船A01', type: '例行保养', scheduledTime: '2024-01-16 09:00', assignee: '张三', status: 'pending' },
{ planId: 'M002', deviceId: 'UD-2025001', deviceName: '巡查无人机B01', type: '周期保养', scheduledTime: '2024-01-17 14:00', assignee: '李四', status: 'in_progress' },
{ planId: 'M003', deviceId: 'IC-2025001', deviceName: '智能摄像头C01', type: '条件保养', scheduledTime: '2024-01-15 10:00', assignee: '王五', status: 'completed' }
];
// 加载维护保养数据
function loadMaintenanceData() {
const maintenanceTableBody = document.getElementById('maintenanceTableBody');
if (!maintenanceTableBody) return;
const statusMap = {
'pending': { text: '待执行', class: 'status-maintenance' },
'in_progress': { text: '进行中', class: 'status-online' },
'completed': { text: '已完成', class: 'status-online' }
};
maintenanceTableBody.innerHTML = maintenanceData.map(plan => `
<tr>
<td>${plan.planId}</td>
<td>${plan.deviceId}</td>
<td>${plan.deviceName}</td>
<td>${plan.type}</td>
<td>${plan.scheduledTime}</td>
<td>${plan.assignee}</td>
<td><span class="status-badge ${statusMap[plan.status].class}">${statusMap[plan.status].text}</span></td>
<td>
<button class="btn btn-primary" onclick="viewMaintenance('${plan.planId}')">查看</button>
<button class="btn btn-success" onclick="executeMaintenance('${plan.planId}')">执行</button>
</td>
</tr>
`).join('');
}
const repairData = [
{ repairId: 'R001', deviceId: 'UC-2025001', fault: '推进器过载', reporter: '张三', repairer: '李四', priority: 'high', status: 'pending' },
{ repairId: 'R002', deviceId: 'UD-2025001', fault: '电池无法充电', reporter: '王五', repairer: '赵六', priority: 'medium', status: 'in_progress' },
{ repairId: 'R003', deviceId: 'IC-2025001', fault: '镜头模糊', reporter: '张三', repairer: '李四', priority: 'low', status: 'completed' }
];
// 加载故障维修数据
function loadRepairData() {
const repairTableBody = document.getElementById('repairTableBody');
if (!repairTableBody) return;
const statusMap = {
'pending': { text: '待维修', class: 'status-maintenance' },
'in_progress': { text: '维修中', class: 'status-online' },
'completed': { text: '已完成', class: 'status-online' }
};
const priorityMap = {
'high': { text: '紧急', class: 'status-fault' },
'medium': { text: '一般', class: 'status-maintenance' },
'low': { text: '低', class: 'status-online' }
};
repairTableBody.innerHTML = repairData.map(repair => `
<tr>
<td>${repair.repairId}</td>
<td>${repair.deviceId}</td>
<td>${repair.fault}</td>
<td>${repair.reporter}</td>
<td>${repair.repairer}</td>
<td><span class="status-badge ${priorityMap[repair.priority].class}">${priorityMap[repair.priority].text}</span></td>
<td><span class="status-badge ${statusMap[repair.status].class}">${statusMap[repair.status].text}</span></td>
<td>
<button class="btn btn-primary" onclick="viewRepair('${repair.repairId}')">查看</button>
<button class="btn btn-success" onclick="processRepair('${repair.repairId}')">处理</button>
</td>
</tr>
`).join('');
}
const partsData = [
{ partId: 'P001', name: '无人船专用电池', device: '打捞无人船', stock: 8, minStock: 5, price: '2000', supplier: '科技公司A' },
{ partId: 'P002', name: '无人机螺旋桨', device: '巡查无人机', stock: 3, minStock: 10, price: '150', supplier: '科技公司B' },
{ partId: 'P003', name: '摄像头镜头', device: '智能摄像头', stock: 15, minStock: 8, price: '800', supplier: '科技公司C' },
{ partId: 'P004', name: '转运车轮胎', device: '密闭转运车', stock: 6, minStock: 4, price: '500', supplier: '轮胎公司D' }
];
// 加载备件管理数据
function loadPartsData() {
const partsTableBody = document.getElementById('partsTableBody');
if (!partsTableBody) return;
partsTableBody.innerHTML = partsData.map(part => {
const isLowStock = part.stock < part.minStock;
const stockClass = isLowStock ? 'status-fault' : 'status-online';
return `
<tr>
<td>${part.partId}</td>
<td>${part.name}</td>
<td>${part.device}</td>
<td><span class="status-badge ${stockClass}">${part.stock}</span></td>
<td>${part.minStock}</td>
<td>¥${part.price}</td>
<td>${part.supplier}</td>
<td>
<button class="btn btn-primary" onclick="viewPart('${part.partId}')">查看</button>
<button class="btn btn-warning" onclick="orderPart('${part.partId}')">采购</button>
</td>
</tr>
`;
}).join('');
}
const disposalData = [
{ applicationId: 'D001', deviceId: 'UC-2024001', deviceName: '垃圾打捞无人船X01', reason: '使用年限到期', applicant: '张三', applyTime: '2024-01-10', status: 'pending' },
{ applicationId: 'D002', deviceId: 'UD-2023001', deviceName: '巡查无人机Y01', reason: '维修成本过高', applicant: '李四', applyTime: '2024-01-08', status: 'approved' },
{ applicationId: 'D003', deviceId: 'IC-2023002', deviceName: '智能摄像头Z01', reason: '技术落后', applicant: '王五', applyTime: '2024-01-05', status: 'rejected' }
];
// 加载报废处置数据
function loadDisposalData() {
const disposalTableBody = document.getElementById('disposalTableBody');
if (!disposalTableBody) return;
const statusMap = {
'pending': { text: '待审批', class: 'status-maintenance' },
'approved': { text: '已批准', class: 'status-online' },
'rejected': { text: '已驳回', class: 'status-fault' }
};
disposalTableBody.innerHTML = disposalData.map(disposal => `
<tr>
<td>${disposal.applicationId}</td>
<td>${disposal.deviceId}</td>
<td>${disposal.deviceName}</td>
<td>${disposal.reason}</td>
<td>${disposal.applicant}</td>
<td>${disposal.applyTime}</td>
<td><span class="status-badge ${statusMap[disposal.status].class}">${statusMap[disposal.status].text}</span></td>
<td>
<button class="btn btn-primary" onclick="viewDisposal('${disposal.applicationId}')">查看</button>
<button class="btn btn-success" onclick="approveDisposal('${disposal.applicationId}')">审批</button>
</td>
</tr>
`).join('');
}
// 加载统计分析数据
function loadAnalysisData() {
// 更新统计数据
document.getElementById('totalDevices').textContent = '45';
document.getElementById('onlineRate').textContent = '87.2%';
document.getElementById('utilizationRate').textContent = '73.5%';
document.getElementById('faultRate').textContent = '2.3%';
// 获取当前选择的统计周期和分析维度
const period = document.getElementById('analysisPeriod').value;
const dimension = document.getElementById('analysisDimension').value;
// 更新分析图表
updateAnalysisChart(period, dimension);
}
// 加载设备告警
function loadDeviceAlerts() {
const deviceAlerts = document.getElementById('deviceAlerts');
if (!deviceAlerts) return;
const alerts = [
{ id: 'UC-2025001', title: '无人船电量低', time: '14:30', level: '警告' },
{ id: 'UD-2025001', title: '无人机离线超时', time: '12:15', level: '严重' },
{ id: 'P002', title: '螺旋桨库存不足', time: '10:00', level: '提醒' }
];
deviceAlerts.innerHTML = alerts.map(alert => `
<div class="alert-item">
<div class="alert-title">${alert.title}</div>
<div class="alert-info">
<span>${alert.time}</span>
<span>${alert.level}</span>
</div>
</div>
`).join('');
}
// 加载维护提醒
function loadMaintenanceReminders() {
const maintenanceReminders = document.getElementById('maintenanceReminders');
if (!maintenanceReminders) return;
const reminders = [
{ id: 'UC-2025001', title: '无人船例行保养', time: '明天 09:00', type: '即将到期' },
{ id: 'IC-2025001', title: '摄像头清洁保养', time: '后天 14:00', type: '计划中' },
{ id: 'MT-2025001', title: '转运车全面检修', time: '本周五', type: '计划中' }
];
maintenanceReminders.innerHTML = reminders.map(reminder => `
<div class="alert-item">
<div class="alert-title">${reminder.title}</div>
<div class="alert-info">
<span>${reminder.time}</span>
<span>${reminder.type}</span>
</div>
</div>
`).join('');
}
// 模态框操作
function openDeviceModal() {
document.getElementById('deviceModal').style.display = 'block';
}
function closeDeviceModal() {
document.getElementById('deviceModal').style.display = 'none';
}
function openMaintenanceModal() {
document.getElementById('maintenanceModal').style.display = 'block';
}
function closeMaintenanceModal() {
document.getElementById('maintenanceModal').style.display = 'none';
}
// 表单提交
document.getElementById('deviceForm').addEventListener('submit', function (e) {
e.preventDefault();
// 获取表单数据
const formData = new FormData(this);
const deviceData = {
id: formData.get('deviceId'),
name: formData.get('deviceName'),
type: formData.get('deviceType'),
icon: getDeviceIcon(formData.get('deviceType')),
area: getAreaName(formData.get('area')),
manager: getManagerName(formData.get('manager')),
status: 'online', // 默认设置为在线状态
battery: '100%', // 默认电量
workTime: '0h', // 初始工作时长
lastMaintenance: new Date().toISOString().split('T')[0] // 当前日期
};
// 添加到设备列表
addDeviceToArchive(deviceData);
alert('设备档案创建成功!');
closeDeviceModal();
loadDeviceArchive(); // 重新加载设备档案
});
// 辅助函数:根据设备类型获取图标
function getDeviceIcon(type) {
const icons = {
'ship': '🚢',
'drone': '🚁',
'camera': '📹',
'truck': '🚛'
};
return icons[type] || '📱';
}
// 辅助函数根据manager值获取显示名称
function getAreaName(area) {
const areas = {
'yuelu': '岳麓区',
'tianxin': '天心区',
'kaifu': '开福区',
'yuhua': '雨花区'
};
return areas[area] || area;
}
// 辅助函数根据manager值获取显示名称
function getManagerName(manager) {
const managers = {
'zhang': '张三',
'li': '李四',
'wang': '王五',
'zhao': '赵六'
};
return managers[manager] || manager;
}
document.getElementById('maintenanceForm').addEventListener('submit', function (e) {
e.preventDefault();
alert('维护计划创建成功!');
closeMaintenanceModal();
loadMaintenanceData();
});
// 其他操作函数
// 查看设备详情
function viewDevice(id) {
const device = devices.find(d => d.id === id);
if (!device) return;
// 填充查看模态框内容
const detailsContent = document.getElementById('deviceDetailsContent');
detailsContent.innerHTML = `
<div class="detail-item">
<div class="detail-label">设备编号</div>
<div class="detail-value">${device.id}</div>
</div>
<div class="detail-item">
<div class="detail-label">设备名称</div>
<div class="detail-value">${device.name}</div>
</div>
<div class="detail-item">
<div class="detail-label">设备类型</div>
<div class="detail-value">${getDeviceTypeName(device.type)}</div>
</div>
<div class="detail-item">
<div class="detail-label">所属区域</div>
<div class="detail-value">${device.area}</div>
</div>
<div class="detail-item">
<div class="detail-label">管理责任人</div>
<div class="detail-value">${device.manager}</div>
</div>
<div class="detail-item">
<div class="detail-label">设备状态</div>
<div class="detail-value">
<span class="status-badge ${getStatusClass(device.status)}">${getStatusName(device.status)}</span>
</div>
</div>
<div class="detail-item">
<div class="detail-label">当前电量</div>
<div class="detail-value">${device.battery}</div>
</div>
<div class="detail-item">
<div class="detail-label">累计工作时长</div>
<div class="detail-value">${device.workTime}</div>
</div>
<div class="detail-item">
<div class="detail-label">上次维护时间</div>
<div class="detail-value">${device.lastMaintenance}</div>
</div>
`;
// 显示查看模态框
document.getElementById('viewDeviceModal').style.display = 'block';
}
// 编辑设备
function editDevice(id) {
const device = devices.find(d => d.id === id);
if (!device) return;
// 填充编辑表单
document.getElementById('editDeviceId').value = device.id;
document.getElementById('editDeviceName').value = device.name;
document.getElementById('editDeviceType').value = device.type;
// 修复区域选择问题 - 直接使用设备中的区域值
const areaValue = device.area.replace('沿岸', '').toLowerCase();
document.getElementById('editDeviceArea').value = areaValue;
document.getElementById('editDeviceManager').value = getManagerValue(device.manager);
document.getElementById('editDeviceStatus').value = device.status;
// 显示编辑模态框
document.getElementById('editDeviceModal').style.display = 'block';
}
// 关闭查看模态框
function closeViewDeviceModal() {
document.getElementById('viewDeviceModal').style.display = 'none';
}
// 关闭编辑模态框
function closeEditDeviceModal() {
document.getElementById('editDeviceModal').style.display = 'none';
}
// 辅助函数:获取设备类型名称
function getDeviceTypeName(type) {
const typeNames = {
'ship': '打捞无人船',
'drone': '巡查无人机',
'camera': '智能摄像头',
'truck': '密闭转运车'
};
return typeNames[type] || type;
}
// 辅助函数:获取状态名称
function getStatusName(status) {
const statusNames = {
'online': '在线',
'offline': '离线',
'maintenance': '维护中',
'fault': '故障'
};
return statusNames[status] || status;
}
// 辅助函数:获取状态类名
function getStatusClass(status) {
const statusClasses = {
'online': 'status-online',
'offline': 'status-offline',
'maintenance': 'status-maintenance',
'fault': 'status-fault'
};
return statusClasses[status] || '';
}
// 辅助函数根据显示名称获取manager值
function getManagerValue(managerName) {
const managers = {
'张三': 'zhang',
'李四': 'li',
'王五': 'wang',
'赵六': 'zhao'
};
return managers[managerName] || managerName;
}
// 处理编辑表单提交
document.getElementById('editDeviceForm').addEventListener('submit', function (e) {
e.preventDefault();
const deviceId = document.getElementById('editDeviceId').value;
const device = devices.find(d => d.id === deviceId);
if (!device) return;
// 更新设备信息
device.name = document.getElementById('editDeviceName').value;
device.type = document.getElementById('editDeviceType').value;
device.area = document.getElementById('editDeviceArea').options[document.getElementById('editDeviceArea').selectedIndex].text;
device.manager = getManagerName(document.getElementById('editDeviceManager').value);
device.status = document.getElementById('editDeviceStatus').value;
// 重新加载设备档案
loadDeviceArchive();
closeEditDeviceModal();
alert('设备信息更新成功!');
});
// 查看设备详情
function viewDetails(id) {
const device = monitorData.find(d => d.id === id);
if (!device) return;
// 填充查看模态框内容
const detailsContent = document.getElementById('deviceDetailsContents');
detailsContent.innerHTML = `
<div class="detail-item">
<div class="detail-label">设备编号</div>
<div class="detail-value">${device.id}</div>
</div>
<div class="detail-item">
<div class="detail-label">设备名称</div>
<div class="detail-value">${device.name}</div>
</div>
<div class="detail-item">
<div class="detail-label">设备类型</div>
<div class="detail-value">${device.type}</div>
</div>
<div class="detail-item">
<div class="detail-label">当前位置</div>
<div class="detail-value">${device.location}</div>
</div>
<div class="detail-item">
<div class="detail-label">电量/状态</div>
<div class="detail-value">${device.battery}</div>
</div>
<div class="detail-item">
<div class="detail-label">在线状态</div>
<div class="detail-value">
<span class="status-badge ${getStatusClass(device.status)}">${getStatusName(device.status)}</span>
</div>
</div>
<div class="detail-item">
<div class="detail-label">最后更新时间</div>
<div class="detail-value">${device.lastUpdate}</div>
</div>
`;
// 显示查看模态框
document.getElementById('viewDetailsModal').style.display = 'block';
}
// 关闭查看详情模态框
function closeViewDetailsModal() {
document.getElementById('viewDetailsModal').style.display = 'none';
}
// 全局变量存储使用的备件
let usedParts = [];
// 打开执行维护模态框
function executeMaintenance(id) {
const maintenance = maintenanceData.find(m => m.planId === id);
if (!maintenance) return;
// 填充执行表单
document.getElementById('executePlanId').value = maintenance.planId;
document.getElementById('executePlanNo').textContent = maintenance.planId;
document.getElementById('executeDeviceName').textContent = maintenance.deviceName;
document.getElementById('executeMaintenanceType').textContent = maintenance.type;
document.getElementById('executeScheduledTime').textContent = maintenance.scheduledTime;
document.getElementById('executeAssignee').textContent = maintenance.assignee;
// 设置默认实际执行时间为当前时间
const now = new Date();
const timezoneOffset = now.getTimezoneOffset() * 60000;
const localISOTime = new Date(now - timezoneOffset).toISOString().slice(0, 16);
document.getElementById('executeActualTime').value = localISOTime;
// 重置表单
document.getElementById('executeMaintenanceForm').reset();
usedParts = [];
document.getElementById('usedPartsList').innerHTML = '';
document.getElementById('photoPreview').innerHTML = '';
// 显示执行模态框
document.getElementById('executeMaintenanceModal').style.display = 'block';
}
// 关闭执行维护模态框
function closeExecuteMaintenanceModal() {
document.getElementById('executeMaintenanceModal').style.display = 'none';
}
// 添加使用的备件
function addUsedPart() {
const partSelect = document.getElementById('executePartSelect');
const partQuantity = document.getElementById('executePartQuantity');
if (!partSelect.value || !partQuantity.value || parseInt(partQuantity.value) <= 0) {
alert('请选择备件并输入有效数量');
return;
}
const partId = partSelect.value;
const partName = partSelect.options[partSelect.selectedIndex].text.split(' - ')[1];
const quantity = parseInt(partQuantity.value);
// 检查是否已添加过该备件
const existingPart = usedParts.find(p => p.partId === partId);
if (existingPart) {
existingPart.quantity += quantity;
} else {
usedParts.push({
partId: partId,
partName: partName,
quantity: quantity
});
}
// 更新备件列表显示
updateUsedPartsList();
// 重置选择
partSelect.value = '';
partQuantity.value = '1';
}
// 更新使用的备件列表显示
function updateUsedPartsList() {
const partsList = document.getElementById('usedPartsList');
partsList.innerHTML = '';
usedParts.forEach((part, index) => {
const row = document.createElement('tr');
row.innerHTML = `
<td style="padding: 8px; border-bottom: 1px solid #e1e9f5;">${part.partId}</td>
<td style="padding: 8px; border-bottom: 1px solid #e1e9f5;">${part.partName}</td>
<td style="padding: 8px; text-align: right; border-bottom: 1px solid #e1e9f5;">${part.quantity}</td>
<td style="padding: 8px; text-align: center; border-bottom: 1px solid #e1e9f5;">
<button class="btn btn-danger" onclick="removeUsedPart(${index})" style="padding: 2px 8px; font-size: 12px;">删除</button>
</td>
`;
partsList.appendChild(row);
});
}
// 移除使用的备件
function removeUsedPart(index) {
usedParts.splice(index, 1);
updateUsedPartsList();
}
// 处理执行表单提交
document.getElementById('executeMaintenanceForm').addEventListener('submit', function (e) {
e.preventDefault();
const planId = document.getElementById('executePlanId').value;
const actualTime = document.getElementById('executeActualTime').value;
const operator = document.getElementById('executeOperator').value;
const result = document.getElementById('executeResult').value;
const deviceStatus = document.getElementById('executeDeviceStatus').value;
const photos = document.getElementById('executePhotos').files;
// 更新维护计划状态
const maintenance = maintenanceData.find(m => m.planId === planId);
if (maintenance) {
maintenance.status = 'completed';
maintenance.actualTime = actualTime;
maintenance.operator = operator;
maintenance.result = result;
maintenance.deviceStatus = deviceStatus;
maintenance.usedParts = [...usedParts];
maintenance.completeTime = new Date().toISOString().split('T')[0];
// 这里可以添加实际业务逻辑,如更新库存、发送到后端等
// 重新加载维护计划数据
loadMaintenanceData();
alert('维护计划执行结果已提交!');
closeExecuteMaintenanceModal();
}
});
// 照片预览功能
document.getElementById('executePhotos').addEventListener('change', function (e) {
const preview = document.getElementById('photoPreview');
preview.innerHTML = '';
Array.from(e.target.files).forEach(file => {
if (!file.type.match('image.*')) return;
const reader = new FileReader();
reader.onload = function (e) {
const img = document.createElement('img');
img.src = e.target.result;
img.style.width = '100px';
img.style.height = '100px';
img.style.objectFit = 'cover';
img.style.borderRadius = '4px';
img.style.margin = '5px';
preview.appendChild(img);
};
reader.readAsDataURL(file);
});
});
function viewRepair(id) {
alert('查看维修单: ' + id);
}
// 全局变量存储维修措施和使用的备件
let repairActions = [];
let repairParts = [];
// 打开处理维修模态框
function processRepair(id) {
const repair = repairData.find(r => r.repairId === id);
if (!repair) return;
// 填充处理表单
document.getElementById('processRepairId').value = repair.repairId;
document.getElementById('processRepairNo').textContent = repair.repairId;
document.getElementById('processDeviceName').textContent = getDeviceName(repair.deviceId);
document.getElementById('processFaultDesc').textContent = repair.fault;
document.getElementById('processReporter').textContent = repair.reporter;
// 设置紧急程度显示
const priorityText = {
'high': '<span class="status-badge status-fault">紧急</span>',
'medium': '<span class="status-badge status-maintenance">一般</span>',
'low': '<span class="status-badge status-online">低</span>'
};
document.getElementById('processPriority').innerHTML = priorityText[repair.priority] || repair.priority;
// 设置默认开始时间为当前时间
const now = new Date();
const timezoneOffset = now.getTimezoneOffset() * 60000;
const localISOTime = new Date(now - timezoneOffset).toISOString().slice(0, 16);
document.getElementById('repairStartTime').value = localISOTime;
// 如果是已处理的,禁用表单并显示结果
if (repair.status !== 'pending') {
document.querySelectorAll('#processRepairForm input, #processRepairForm select, #processRepairForm textarea')
.forEach(el => el.disabled = true);
document.getElementById('repairTechnician').value = repair.technician || '';
document.getElementById('repairStartTime').value = repair.startTime || '';
document.getElementById('repairDiagnosis').value = repair.diagnosis || '';
document.getElementById('repairResult').value = repair.result || '';
document.getElementById('repairNotes').value = repair.notes || '';
document.getElementById('repairDeviceStatus').value = repair.deviceStatus || '';
document.querySelector('#processRepairForm button[type="submit"]').style.display = 'none';
// 显示已有的维修措施和备件
if (repair.actions) {
repairActions = [...repair.actions];
updateRepairActionsList();
}
if (repair.usedParts) {
repairParts = [...repair.usedParts];
updateRepairPartsList();
}
} else {
// 重置表单
document.getElementById('processRepairForm').reset();
repairActions = [];
repairParts = [];
document.getElementById('repairActionsList').innerHTML = '';
document.getElementById('repairPartsList').innerHTML = '';
document.getElementById('repairPhotoPreview').innerHTML = '';
document.querySelectorAll('#processRepairForm input, #processRepairForm select, #processRepairForm textarea')
.forEach(el => el.disabled = false);
document.querySelector('#processRepairForm button[type="submit"]').style.display = 'inline-block';
}
// 显示处理模态框
document.getElementById('processRepairModal').style.display = 'block';
}
// 关闭处理维修模态框
function closeProcessRepairModal() {
document.getElementById('processRepairModal').style.display = 'none';
}
// 添加维修措施
function addRepairAction() {
const actionSelect = document.getElementById('repairActionSelect');
if (!actionSelect.value) {
alert('请选择维修措施类型');
return;
}
const actionType = actionSelect.value;
const actionText = actionSelect.options[actionSelect.selectedIndex].text.split('-')[1] || actionSelect.options[actionSelect.selectedIndex].text;
const actionDesc = prompt(`请输入"${actionText}"的详细说明`, "");
if (actionDesc === null || actionDesc.trim() === "") {
alert('必须输入维修措施详细说明');
return;
}
repairActions.push({
type: actionType,
description: actionDesc
});
// 更新维修措施列表显示
updateRepairActionsList();
// 重置选择
actionSelect.value = '';
}
// 更新维修措施列表显示
function updateRepairActionsList() {
const actionsList = document.getElementById('repairActionsList');
actionsList.innerHTML = '';
repairActions.forEach((action, index) => {
const typeText = {
'replace': '更换部件',
'repair': '修复部件',
'adjust': '调整参数',
'clean': '清洁维护',
'software': '软件修复'
};
const row = document.createElement('tr');
row.innerHTML = `
<td style="padding: 8px; border-bottom: 1px solid #e1e9f5;">${typeText[action.type] || action.type}</td>
<td style="padding: 8px; border-bottom: 1px solid #e1e9f5;">${action.description}</td>
<td style="padding: 8px; text-align: center; border-bottom: 1px solid #e1e9f5;">
<button class="btn btn-danger" onclick="removeRepairAction(${index})" style="padding: 2px 8px; font-size: 12px;">删除</button>
</td>
`;
actionsList.appendChild(row);
});
}
// 移除维修措施
function removeRepairAction(index) {
repairActions.splice(index, 1);
updateRepairActionsList();
}
// 添加维修使用的备件
function addRepairPart() {
const partSelect = document.getElementById('repairPartSelect');
const partQuantity = document.getElementById('repairPartQuantity');
if (!partSelect.value || !partQuantity.value || parseInt(partQuantity.value) <= 0) {
alert('请选择备件并输入有效数量');
return;
}
const partId = partSelect.value;
const partName = partSelect.options[partSelect.selectedIndex].text.split(' - ')[1];
const quantity = parseInt(partQuantity.value);
// 检查是否已添加过该备件
const existingPart = repairParts.find(p => p.partId === partId);
if (existingPart) {
existingPart.quantity += quantity;
} else {
repairParts.push({
partId: partId,
partName: partName,
quantity: quantity
});
}
// 更新备件列表显示
updateRepairPartsList();
// 重置选择
partSelect.value = '';
partQuantity.value = '1';
}
// 更新维修使用的备件列表显示
function updateRepairPartsList() {
const partsList = document.getElementById('repairPartsList');
partsList.innerHTML = '';
repairParts.forEach((part, index) => {
const row = document.createElement('tr');
row.innerHTML = `
<td style="padding: 8px; border-bottom: 1px solid #e1e9f5;">${part.partId}</td>
<td style="padding: 8px; border-bottom: 1px solid #e1e9f5;">${part.partName}</td>
<td style="padding: 8px; text-align: right; border-bottom: 1px solid #e1e9f5;">${part.quantity}</td>
<td style="padding: 8px; text-align: center; border-bottom: 1px solid #e1e9f5;">
<button class="btn btn-danger" onclick="removeRepairPart(${index})" style="padding: 2px 8px; font-size: 12px;">删除</button>
</td>
`;
partsList.appendChild(row);
});
}
// 移除维修使用的备件
function removeRepairPart(index) {
repairParts.splice(index, 1);
updateRepairPartsList();
}
// 处理维修表单提交
document.getElementById('processRepairForm').addEventListener('submit', function (e) {
e.preventDefault();
const repairId = document.getElementById('processRepairId').value;
const technician = document.getElementById('repairTechnician').value;
const startTime = document.getElementById('repairStartTime').value;
const diagnosis = document.getElementById('repairDiagnosis').value;
const result = document.getElementById('repairResult').value;
const notes = document.getElementById('repairNotes').value;
const deviceStatus = document.getElementById('repairDeviceStatus').value;
// 更新维修单状态
const repair = repairData.find(r => r.repairId === repairId);
if (repair) {
repair.status = 'completed';
repair.technician = technician;
repair.startTime = startTime;
repair.endTime = new Date().toISOString().split('T')[0];
repair.diagnosis = diagnosis;
repair.actions = [...repairActions];
repair.usedParts = [...repairParts];
repair.result = result;
repair.notes = notes;
repair.deviceStatus = deviceStatus;
repair.processor = getCurrentUser().name; // 只存储用户名
// 更新备件库存(模拟)
updatePartsInventory(repair.usedParts);
// 重新加载维修数据
loadRepairData();
alert('维修处理结果已提交!');
closeProcessRepairModal();
}
});
// 更新备件库存(模拟函数)
function updatePartsInventory(usedParts) {
usedParts.forEach(usedPart => {
const part = partsData.find(p => p.partId === usedPart.partId);
if (part) {
part.stock = Math.max(0, part.stock - usedPart.quantity);
}
});
// 重新加载备件数据
loadPartsData();
}
// 维修照片预览功能
document.getElementById('repairPhotos').addEventListener('change', function (e) {
const preview = document.getElementById('repairPhotoPreview');
preview.innerHTML = '';
Array.from(e.target.files).forEach(file => {
if (!file.type.match('image.*')) return;
const reader = new FileReader();
reader.onload = function (e) {
const img = document.createElement('img');
img.src = e.target.result;
img.style.width = '100px';
img.style.height = '100px';
img.style.objectFit = 'cover';
img.style.borderRadius = '4px';
img.style.margin = '5px';
preview.appendChild(img);
};
reader.readAsDataURL(file);
});
});
// 获取当前用户(模拟函数,实际应用中应从登录信息获取)
function getCurrentUser() {
// 这里只是一个示例,实际应用中应该返回当前登录的用户信息
return {
id: "current_user",
name: "当前用户"
};
}
// 查看备件详情
function viewPart(id) {
const part = partsData.find(p => p.partId === id);
if (!part) return;
// 填充查看模态框内容
const detailsContent = document.getElementById('partDetailsContent');
detailsContent.innerHTML = `
<div class="detail-item">
<div class="detail-label">备件编号</div>
<div class="detail-value">${part.partId}</div>
</div>
<div class="detail-item">
<div class="detail-label">备件名称</div>
<div class="detail-value">${part.name}</div>
</div>
<div class="detail-item">
<div class="detail-label">适用设备</div>
<div class="detail-value">${part.device}</div>
</div>
<div class="detail-item">
<div class="detail-label">当前库存</div>
<div class="detail-value">
<span class="status-badge ${part.stock < part.minStock ? 'status-fault' : 'status-online'}">
${part.stock}
</span>
</div>
</div>
<div class="detail-item">
<div class="detail-label">最低库存</div>
<div class="detail-value">${part.minStock}</div>
</div>
<div class="detail-item">
<div class="detail-label">单价</div>
<div class="detail-value">¥${part.price}</div>
</div>
<div class="detail-item">
<div class="detail-label">供应商</div>
<div class="detail-value">${part.supplier}</div>
</div>
<div class="detail-item">
<div class="detail-label">库存状态</div>
<div class="detail-value">
<span class="status-badge ${part.stock < part.minStock ? 'status-fault' : 'status-online'}">
${part.stock < part.minStock ? '库存不足' : '库存正常'}
</span>
</div>
</div>
<div class="detail-item" style="grid-column: 1 / -1;">
<div class="detail-label">备件描述</div>
<div class="detail-value" style="min-height: 60px;">
${getPartDescription(part.partId)}
</div>
</div>
`;
// 显示查看模态框
document.getElementById('viewPartModal').style.display = 'block';
}
// 关闭查看备件详情模态框
function closeViewPartModal() {
document.getElementById('viewPartModal').style.display = 'none';
}
// 辅助函数:获取备件描述
function getPartDescription(partId) {
const descriptions = {
'P001': '无人船专用锂电池容量5000mAh电压24V适用于UC系列无人船',
'P002': '无人机备用螺旋桨材质为碳纤维尺寸8英寸适用于UD系列无人机',
'P003': '高清摄像头镜头200万像素防水防雾适用于IC系列智能摄像头',
'P004': '转运车实心轮胎尺寸18英寸耐磨防滑适用于MT系列转运车'
};
return descriptions[partId] || '暂无详细描述';
}
// 全局变量存储采购记录
let purchaseRecords = [];
// 打开采购模态框
function orderPart(id) {
const part = partsData.find(p => p.partId === id);
if (!part) return;
// 填充采购表单
document.getElementById('orderPartId').value = part.partId;
document.getElementById('orderPartName').value = part.name;
document.getElementById('orderPartDevice').value = part.device;
document.getElementById('orderCurrentStock').value = part.stock;
document.getElementById('orderMinStock').value = part.minStock;
document.getElementById('orderUnitPrice').value = `¥${part.price}`;
document.getElementById('orderSupplier').value = part.supplier;
// 设置默认预计到货时间为3天后
const threeDaysLater = new Date();
threeDaysLater.setDate(threeDaysLater.getDate() + 3);
document.getElementById('orderExpectedDate').valueAsDate = threeDaysLater;
// 计算总价
updateOrderTotalPrice();
// 显示采购模态框
document.getElementById('orderPartModal').style.display = 'block';
}
// 更新采购总价
function updateOrderTotalPrice() {
const quantity = parseInt(document.getElementById('orderQuantity').value) || 0;
const priceText = document.getElementById('orderUnitPrice').value;
const price = parseInt(priceText.replace(/[^0-9]/g, '')) || 0;
const total = quantity * price;
document.getElementById('orderTotalPrice').value = `¥${total}`;
}
// 关闭采购模态框
function closeOrderPartModal() {
document.getElementById('orderPartModal').style.display = 'none';
document.getElementById('orderPartForm').reset();
}
// 处理采购表单提交
document.getElementById('orderPartForm').addEventListener('submit', function (e) {
e.preventDefault();
const partId = document.getElementById('orderPartId').value;
const quantity = parseInt(document.getElementById('orderQuantity').value);
const purchaser = document.getElementById('orderPurchaser').value;
const expectedDate = document.getElementById('orderExpectedDate').value;
const notes = document.getElementById('orderNotes').value;
// 创建采购记录
const record = {
orderId: 'PO-' + new Date().getTime(),
partId: partId,
partName: document.getElementById('orderPartName').value,
quantity: quantity,
purchaser: purchaser,
orderDate: new Date().toISOString().split('T')[0],
expectedDate: expectedDate,
status: 'pending',
notes: notes
};
// 添加到采购记录
purchaseRecords.push(record);
alert(`采购单已提交!采购单号: ${record.orderId}`);
closeOrderPartModal();
// 这里可以添加实际业务逻辑,如发送到后端等
});
// 查看报废申请详情
function viewDisposal(id) {
const disposal = disposalData.find(d => d.applicationId === id);
if (!disposal) return;
// 填充查看模态框内容
const detailsContent = document.getElementById('disposalDetailsContent');
detailsContent.innerHTML = `
<div class="detail-item">
<div class="detail-label">申请编号</div>
<div class="detail-value">${disposal.applicationId}</div>
</div>
<div class="detail-item">
<div class="detail-label">设备编号</div>
<div class="detail-value">${disposal.deviceId}</div>
</div>
<div class="detail-item">
<div class="detail-label">设备名称</div>
<div class="detail-value">${disposal.deviceName}</div>
</div>
<div class="detail-item">
<div class="detail-label">报废原因</div>
<div class="detail-value">${disposal.reason}</div>
</div>
<div class="detail-item">
<div class="detail-label">申请人</div>
<div class="detail-value">${disposal.applicant}</div>
</div>
<div class="detail-item">
<div class="detail-label">申请时间</div>
<div class="detail-value">${disposal.applyTime}</div>
</div>
<div class="detail-item">
<div class="detail-label">审批状态</div>
<div class="detail-value">
<span class="status-badge ${getDisposalStatusClass(disposal.status)}">
${getDisposalStatusName(disposal.status)}
</span>
</div>
</div>
<div class="detail-item">
<div class="detail-label">技术评估</div>
<div class="detail-value">${disposal.evaluation}</div>
</div>
<div class="detail-item">
<div class="detail-label">处置方式</div>
<div class="detail-value">${disposal.disposalMethod || '待确定'}</div>
</div>
${disposal.approvalComments ? `
<div class="detail-item">
<div class="detail-label">审批意见</div>
<div class="detail-value">${disposal.approvalComments}</div>
</div>
` : ''}
<div class="detail-item" style="grid-column: 1 / -1;">
<div class="detail-label">设备照片</div>
<div class="detail-value" style="min-height: 100px; background: #f5f9ff; display: flex; align-items: center; justify-content: center; border-radius: 6px;">
<i class="fas fa-camera" style="font-size: 24px; color: #a8c0e0;"></i>
<span style="margin-left: 10px; color: #4a6fa5;">设备照片预览区域</span>
</div>
</div>
`;
// 显示查看模态框
document.getElementById('viewDisposalModal').style.display = 'block';
}
// 关闭查看报废详情模态框
function closeViewDisposalModal() {
document.getElementById('viewDisposalModal').style.display = 'none';
}
// 辅助函数:获取报废状态名称
function getDisposalStatusName(status) {
const statusNames = {
'pending': '待审批',
'approved': '已批准',
'rejected': '已驳回'
};
return statusNames[status] || status;
}
// 辅助函数:获取报废状态类名
function getDisposalStatusClass(status) {
const statusClasses = {
'pending': 'status-maintenance',
'approved': 'status-online',
'rejected': 'status-fault'
};
return statusClasses[status] || '';
}
// 打开审批模态框
function approveDisposal(id) {
const disposal = disposalData.find(d => d.applicationId === id);
if (!disposal) return;
// 填充审批表单
document.getElementById('approveDisposalId').value = disposal.applicationId;
document.getElementById('approveAppId').textContent = disposal.applicationId;
document.getElementById('approveDeviceName').textContent = disposal.deviceName;
document.getElementById('approveReason').textContent = disposal.reason;
document.getElementById('approveApplicant').textContent = disposal.applicant;
document.getElementById('approveApplyTime').textContent = disposal.applyTime;
document.getElementById('approveEvaluation').textContent = disposal.evaluation;
// 重置表单
document.getElementById('approveDisposalForm').reset();
// 如果是已审批的,禁用表单并显示结果
if (disposal.status !== 'pending') {
document.querySelectorAll('#approveDisposalForm input, #approveDisposalForm select, #approveDisposalForm textarea')
.forEach(el => el.disabled = true);
document.querySelector(`input[name="approvalResult"][value="${disposal.status}"]`).checked = true;
document.getElementById('disposalMethod').value = disposal.disposalMethod || '';
document.getElementById('approvalComments').value = disposal.approvalComments || '';
document.getElementById('approver').value = disposal.approver || '';
document.querySelector('#approveDisposalForm button[type="submit"]').style.display = 'none';
} else {
document.querySelectorAll('#approveDisposalForm input, #approveDisposalForm select, #approveDisposalForm textarea')
.forEach(el => el.disabled = false);
document.querySelector('#approveDisposalForm button[type="submit"]').style.display = 'inline-block';
}
// 显示审批模态框
document.getElementById('approveDisposalModal').style.display = 'block';
}
// 关闭审批模态框
function closeApproveDisposalModal() {
document.getElementById('approveDisposalModal').style.display = 'none';
}
// 处理审批表单提交
document.getElementById('approveDisposalForm').addEventListener('submit', function (e) {
e.preventDefault();
const disposalId = document.getElementById('approveDisposalId').value;
const result = document.querySelector('input[name="approvalResult"]:checked').value;
const disposalMethod = document.getElementById('disposalMethod').value;
const comments = document.getElementById('approvalComments').value;
const approver = document.getElementById('approver').value;
// 更新报废申请状态
const disposal = disposalData.find(d => d.applicationId === disposalId);
if (disposal) {
disposal.status = result;
disposal.disposalMethod = disposalMethod;
disposal.approvalComments = comments;
disposal.approver = approver;
disposal.approveTime = new Date().toISOString().split('T')[0];
// 重新加载报废处置数据
loadDisposalData();
alert(`报废申请已${result === 'approved' ? '批准' : '驳回'}`);
closeApproveDisposalModal();
}
});
function exportReport() {
alert('导出设备报表');
}
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', function () {
// 初始化设备数据
devices = [
{
id: 'UC-2025001',
name: '垃圾打捞无人船A01',
type: 'ship',
icon: '🚢',
area: '岳麓区沿岸',
manager: '张三',
status: 'online',
battery: '85%',
workTime: '120h',
lastMaintenance: '2024-01-10'
},
{
id: 'UD-2025001',
name: '巡查无人机B01',
type: 'drone',
icon: '🚁',
area: '天心区沿岸',
manager: '李四',
status: 'offline',
battery: '0%',
workTime: '45h',
lastMaintenance: '2024-01-08'
},
{
id: 'IC-2025001',
name: '智能摄像头C01',
type: 'camera',
icon: '📹',
area: '开福区沿岸',
manager: '王五',
status: 'online',
battery: '正常',
workTime: '720h',
lastMaintenance: '2024-01-05'
},
{
id: 'MT-2025001',
name: '密闭转运车D01',
type: 'truck',
icon: '🚛',
area: '雨花区沿岸',
manager: '赵六',
status: 'maintenance',
battery: '正常',
workTime: '200h',
lastMaintenance: '2024-01-12'
}
];
// 初始化加载设备档案数据
loadDeviceArchive();
// 加载侧边栏数据
loadDeviceAlerts();
loadMaintenanceReminders();
// 设置筛选器事件监听
const deviceTypeFilter = document.getElementById('deviceTypeFilter');
const deviceStatusFilter = document.getElementById('deviceStatusFilter');
const deviceAreaFilter = document.getElementById('deviceAreaFilter');
const deviceSearch = document.getElementById('deviceSearch');
if (deviceTypeFilter) deviceTypeFilter.addEventListener('change', filterDevices);
if (deviceStatusFilter) deviceStatusFilter.addEventListener('change', filterDevices);
if (deviceAreaFilter) deviceAreaFilter.addEventListener('change', filterDevices);
if (deviceSearch) deviceSearch.addEventListener('input', filterDevices);
initCharts();
// 为分析筛选器添加事件监听
document.getElementById('analysisPeriod').addEventListener('change', function () {
const period = this.value;
const dimension = document.getElementById('analysisDimension').value;
updateAnalysisChart(period, dimension);
});
document.getElementById('analysisDimension').addEventListener('change', function () {
const dimension = this.value;
const period = document.getElementById('analysisPeriod').value;
updateAnalysisChart(period, dimension);
});
});
// 设备筛选功能
function filterDevices() {
const typeFilter = document.getElementById('deviceTypeFilter')?.value || 'all';
const statusFilter = document.getElementById('deviceStatusFilter')?.value || 'all';
const areaFilter = document.getElementById('deviceAreaFilter')?.value || 'all';
const searchText = document.getElementById('deviceSearch')?.value.toLowerCase() || '';
const deviceItems = document.querySelectorAll('.device-item');
deviceItems.forEach((item, index) => {
const device = devices[index];
if (!device) return;
const deviceName = device.name.toLowerCase();
const deviceId = device.id.toLowerCase();
const deviceStatus = device.status;
const deviceType = device.type;
const deviceArea = device.area;
let showItem = true;
// 搜索过滤
if (searchText && !deviceName.includes(searchText) && !deviceId.includes(searchText)) {
showItem = false;
}
// 类型过滤
if (typeFilter !== 'all' && deviceType !== typeFilter) {
showItem = false;
}
// 状态过滤
if (statusFilter !== 'all' && deviceStatus !== statusFilter) {
showItem = false;
}
// 区域过滤
if (areaFilter !== 'all' && deviceArea !== areaFilter) {
showItem = false;
}
item.style.display = showItem ? 'block' : 'none';
});
}
// 点击模态框外部关闭
window.onclick = function (event) {
const deviceModal = document.getElementById('deviceModal');
const maintenanceModal = document.getElementById('maintenanceModal');
if (event.target === deviceModal) {
closeDeviceModal();
}
if (event.target === maintenanceModal) {
closeMaintenanceModal();
}
if (event.target === document.getElementById('viewDeviceModal')) {
closeViewDeviceModal();
}
if (event.target === document.getElementById('editDeviceModal')) {
closeEditDeviceModal();
}
if (event.target === document.getElementById('viewDetailsModal')) {
closeViewDetailsModal();
}
if (event.target === document.getElementById('viewMaintenanceModal')) {
closeViewMaintenanceModal();
}
if (event.target === document.getElementById('viewRepairModal')) {
closeViewRepairModal();
}
if (event.target === document.getElementById('viewPartModal')) {
closeViewPartModal();
}
if (event.target === document.getElementById('orderPartModal')) {
closeOrderPartModal();
}
if (event.target === document.getElementById('viewDisposalModal')) {
closeViewDisposalModal();
}
if (event.target === document.getElementById('approveDisposalModal')) {
closeApproveDisposalModal();
}
if (event.target === document.getElementById('executeMaintenanceModal')) {
closeExecuteMaintenanceModal();
}
if (event.target === document.getElementById('processRepairModal')) {
closeProcessRepairModal();
}
}
// 为采购数量输入框添加事件监听
document.getElementById('orderQuantity').addEventListener('input', updateOrderTotalPrice);
// 全局变量存储图表实例
let distributionChart = null;
let analysisChart = null;
// 初始化图表
function initCharts() {
// 设备分布图表数据
const distributionData = {
labels: ['打捞无人船', '巡查无人机', '智能摄像头', '密闭转运车'],
datasets: [{
data: [15, 10, 12, 8],
backgroundColor: [
'#2a7de1',
'#1a4b8c',
'#4a6fa5',
'#a8c0e0'
],
borderColor: '#ffffff',
borderWidth: 1
}]
};
// 设备效能分析图表数据
const analysisData = {
labels: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
datasets: [
{
label: '打捞无人船',
data: [85, 78, 90, 82, 88, 92, 87, 91, 89, 93, 90, 95],
borderColor: '#2a7de1',
backgroundColor: 'rgba(42, 125, 225, 0.1)',
tension: 0.3,
fill: true
},
{
label: '巡查无人机',
data: [78, 82, 85, 80, 83, 87, 85, 88, 86, 90, 92, 94],
borderColor: '#1a4b8c',
backgroundColor: 'rgba(26, 75, 140, 0.1)',
tension: 0.3,
fill: true
},
{
label: '智能摄像头',
data: [92, 90, 88, 91, 93, 95, 94, 96, 95, 97, 96, 98],
borderColor: '#4a6fa5',
backgroundColor: 'rgba(74, 111, 165, 0.1)',
tension: 0.3,
fill: true
},
{
label: '密闭转运车',
data: [80, 82, 85, 83, 86, 88, 87, 89, 90, 92, 93, 95],
borderColor: '#a8c0e0',
backgroundColor: 'rgba(168, 192, 224, 0.1)',
tension: 0.3,
fill: true
}
]
};
// 创建设备分布图表(饼图)
const distributionCtx = document.getElementById('distributionChart').getContext('2d');
distributionChart = new Chart(distributionCtx, {
type: 'pie',
data: distributionData,
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'bottom',
labels: {
color: '#1a4b8c',
font: {
size: 12
}
}
},
tooltip: {
callbacks: {
label: function (context) {
const label = context.label || '';
const value = context.raw || 0;
const total = context.dataset.data.reduce((a, b) => a + b, 0);
const percentage = Math.round((value / total) * 100);
return `${label}: ${value}台 (${percentage}%)`;
}
}
}
}
}
});
// 创建设备效能分析图表(折线图)
// 初始化分析图表空配置实际数据在loadAnalysisData中加载
const analysisCtx = document.getElementById('analysisChart').getContext('2d');
analysisChart = new Chart(analysisCtx, {
type: 'line',
data: { labels: [], datasets: [] },
options: {}
});
// 初始加载分析数据
loadAnalysisData();
}
// 更新分析图表数据 - 简洁线条风格
function updateAnalysisChart(period, dimension) {
// 简洁线条配色方案
const lineColors = [
'#36A2EB', // 亮蓝色
'#FF6384', // 粉色
'#4BC0C0', // 蓝绿色
'#FF9F40', // 橙色
'#9966FF', // 紫色
'#FFCD56' // 黄色
];
// 这里可以根据不同的统计周期和分析维度更新图表数据
let newData;
if (dimension === 'type') {
// 按设备类型分析 - 简洁线条风格
newData = {
labels: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
datasets: [
{
label: '打捞无人船',
data: [85, 78, 90, 82, 88, 92, 87, 91, 89, 93, 90, 95],
borderColor: lineColors[0],
backgroundColor: 'transparent',
borderWidth: 3,
pointBackgroundColor: '#ffffff',
pointBorderColor: lineColors[0],
pointBorderWidth: 2,
pointRadius: 4,
pointHoverRadius: 6,
tension: 0.4,
fill: false
},
{
label: '巡查无人机',
data: [78, 82, 85, 80, 83, 87, 85, 88, 86, 90, 92, 94],
borderColor: lineColors[1],
backgroundColor: 'transparent',
borderWidth: 3,
pointBackgroundColor: '#ffffff',
pointBorderColor: lineColors[1],
pointBorderWidth: 2,
pointRadius: 4,
pointHoverRadius: 6,
tension: 0.4,
fill: false
},
{
label: '智能摄像头',
data: [92, 90, 88, 91, 93, 95, 94, 96, 95, 97, 96, 98],
borderColor: lineColors[2],
backgroundColor: 'transparent',
borderWidth: 3,
pointBackgroundColor: '#ffffff',
pointBorderColor: lineColors[2],
pointBorderWidth: 2,
pointRadius: 4,
pointHoverRadius: 6,
tension: 0.4,
fill: false
},
{
label: '密闭转运车',
data: [80, 82, 85, 83, 86, 88, 87, 89, 90, 92, 93, 95],
borderColor: lineColors[3],
backgroundColor: 'transparent',
borderWidth: 3,
pointBackgroundColor: '#ffffff',
pointBorderColor: lineColors[3],
pointBorderWidth: 2,
pointRadius: 4,
pointHoverRadius: 6,
tension: 0.4,
fill: false
}
]
};
} else if (dimension === 'area') {
// 按区域分布分析 - 简洁线条风格
newData = {
labels: ['岳麓区沿岸', '天心区沿岸', '开福区沿岸', '雨花区沿岸'],
datasets: [
{
label: '设备在线率',
data: [92, 85, 88, 90],
borderColor: lineColors[0],
backgroundColor: 'transparent',
borderWidth: 3,
pointBackgroundColor: '#ffffff',
pointBorderColor: lineColors[0],
pointBorderWidth: 2,
pointRadius: 4,
pointHoverRadius: 6,
tension: 0,
fill: false
},
{
label: '设备利用率',
data: [78, 82, 80, 85],
borderColor: lineColors[1],
backgroundColor: 'transparent',
borderWidth: 3,
pointBackgroundColor: '#ffffff',
pointBorderColor: lineColors[1],
pointBorderWidth: 2,
pointRadius: 4,
pointHoverRadius: 6,
tension: 0,
fill: false
}
]
};
} else if (dimension === 'usage') {
// 按使用频率分析 - 简洁线条风格
newData = {
labels: ['打捞无人船', '巡查无人机', '智能摄像头', '密闭转运车'],
datasets: [
{
label: '日均使用时长(小时)',
data: [8.5, 6.2, 24, 5.8],
borderColor: lineColors[4],
backgroundColor: 'transparent',
borderWidth: 3,
pointBackgroundColor: '#ffffff',
pointBorderColor: lineColors[4],
pointBorderWidth: 2,
pointRadius: 4,
pointHoverRadius: 6,
tension: 0,
fill: false
}
]
};
}
// 更新图表配置
const options = {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'bottom',
labels: {
color: '#555',
font: {
size: 12,
family: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif"
},
padding: 20,
usePointStyle: true,
pointStyle: 'circle'
}
},
tooltip: {
backgroundColor: 'rgba(255, 255, 255, 0.95)',
titleColor: '#333',
bodyColor: '#666',
borderColor: '#ddd',
borderWidth: 1,
padding: 12,
displayColors: true,
usePointStyle: true,
callbacks: {
label: function (context) {
let label = context.dataset.label || '';
if (label) {
label += ': ';
}
if (dimension === 'usage') {
label += context.raw + '小时';
} else {
label += context.raw + '%';
}
return label;
}
}
}
},
scales: {
y: {
beginAtZero: dimension === 'usage' ? true : false,
min: dimension === 'usage' ? 0 : 70,
max: dimension === 'usage' ? 25 : 100,
ticks: {
color: '#888',
font: {
size: 11
},
callback: function (value) {
return dimension === 'usage' ? value + 'h' : value + '%';
}
},
grid: {
color: 'rgba(0, 0, 0, 0.05)',
drawBorder: false
}
},
x: {
ticks: {
color: '#888',
font: {
size: 11
}
},
grid: {
display: false,
drawBorder: false
}
}
},
elements: {
line: {
cubicInterpolationMode: 'monotone'
}
}
};
// 如果是区域和使用频率维度,使用折线图而非柱状图
analysisChart.config.type = 'line';
// 更新图表数据和配置
analysisChart.data = newData;
analysisChart.options = options;
analysisChart.update();
}
// 辅助函数将十六进制颜色转换为RGBA
function hexToRgba(hex, alpha) {
const r = parseInt(hex.slice(1, 3), 16);
const g = parseInt(hex.slice(3, 5), 16);
const b = parseInt(hex.slice(5, 7), 16);
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}
// 全局变量存储设备数据
let devices = [
{
id: 'UC-2025001',
name: '垃圾打捞无人船A01',
type: 'ship',
icon: '🚢',
area: '岳麓区沿岸',
manager: '张三',
status: 'online',
battery: '85%',
workTime: '120h',
lastMaintenance: '2024-01-10'
},
{
id: 'UD-2025001',
name: '巡查无人机B01',
type: 'drone',
icon: '🚁',
area: '天心区沿岸',
manager: '李四',
status: 'offline',
battery: '0%',
workTime: '45h',
lastMaintenance: '2024-01-08'
},
{
id: 'IC-2025001',
name: '智能摄像头C01',
type: 'camera',
icon: '📹',
area: '开福区沿岸',
manager: '王五',
status: 'online',
battery: '正常',
workTime: '720h',
lastMaintenance: '2024-01-05'
},
{
id: 'MT-2025001',
name: '密闭转运车D01',
type: 'truck',
icon: '🚛',
area: '雨花区沿岸',
manager: '赵六',
status: 'maintenance',
battery: '正常',
workTime: '200h',
lastMaintenance: '2024-01-12'
}
];
// 添加新设备到设备列表
function addDeviceToArchive(device) {
devices.push(device);
}
// 地图相关变量
let deviceMap;
let deviceVectorLayer;
// 在script标签中添加以下代码
var TDT_API_KEY = "a4f4b6000cb9d1bf148bb77452000f30";
// 初始化设备地图
function initDeviceMap(deviceId, location) {
const device = monitorData.find(d => d.id === deviceId);
if (!device) return;
document.getElementById('deviceLocationTitle').textContent = `${device.name} - ${device.location}`;
// 创建地图图层
const satelliteLayer = new ol.layer.Tile({
source: new ol.source.XYZ({
url: "http://t{0-7}.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=" + TDT_API_KEY
}),
visible: true,
name: 'satellite'
});
const streetLayer = new ol.layer.Tile({
source: new ol.source.XYZ({
url: "http://t{0-7}.tianditu.com/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=" + TDT_API_KEY
}),
visible: false,
name: 'street'
});
const terrainLayer = new ol.layer.Tile({
source: new ol.source.XYZ({
url: "http://t{0-7}.tianditu.com/DataServer?T=ter_w&x={x}&y={y}&l={z}&tk=" + TDT_API_KEY
}),
visible: false,
name: 'terrain'
});
// 创建地图
deviceMap = new ol.Map({
layers: [satelliteLayer, streetLayer, terrainLayer],
target: 'deviceMap',
view: new ol.View({
projection: 'EPSG:4326',
center: [112.955, 28.195],
zoom: 14
})
});
// 添加设备位置标记
deviceVectorLayer = new ol.layer.Vector({
source: new ol.source.Vector(),
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 8,
fill: new ol.style.Fill({ color: '#2a7de1' }),
stroke: new ol.style.Stroke({ color: 'white', width: 2 })
})
})
});
deviceMap.addLayer(deviceVectorLayer);
// 添加设备位置点
const devicePoint = new ol.Feature({
geometry: new ol.geom.Point([112.955, 28.195]),
name: device.name
});
deviceVectorLayer.getSource().addFeature(devicePoint);
// 调整视图以显示设备位置
deviceMap.getView().fit(devicePoint.getGeometry(), { padding: [50, 50, 50, 50], maxZoom: 16 });
}
// 切换地图类型
function switchDeviceMapType(type) {
document.querySelectorAll('#locationModal .map-controls .map-control-btn').forEach(btn => {
btn.classList.toggle('active', btn.dataset.view === type);
});
deviceMap.getLayers().forEach(layer => {
if (layer.get('name')) {
layer.setVisible(layer.get('name') === type);
}
});
}
// 打开定位模态框
function locateDevice(id) {
const device = monitorData.find(d => d.id === id);
if (!device) return;
document.getElementById('locationModal').style.display = 'block';
//document.getElementById('deviceCoordinates').textContent = `经度: ${device.location[0]}, 纬度: ${device.location[1]}`;
document.getElementById('deviceLocationTitle').textContent = `${device.name}`;
setTimeout(() => {
if (!deviceMap) {
initDeviceMap(id, device.location);
} else {
deviceMap.setTarget('deviceMap');
deviceMap.updateSize();
}
}, 100);
}
// 关闭定位模态框
function closeLocationModal() {
document.getElementById('locationModal').style.display = 'none';
if (deviceMap) {
deviceMap.setTarget(undefined);
}
}
// 查看维护计划详情
function viewMaintenance(id) {
const maintenance = maintenanceData.find(m => m.planId === id);
if (!maintenance) return;
// 填充查看模态框内容
const detailsContent = document.getElementById('maintenanceDetailsContent');
detailsContent.innerHTML = `
<div class="detail-item">
<div class="detail-label">计划编号</div>
<div class="detail-value">${maintenance.planId}</div>
</div>
<div class="detail-item">
<div class="detail-label">设备编号</div>
<div class="detail-value">${maintenance.deviceId}</div>
</div>
<div class="detail-item">
<div class="detail-label">设备名称</div>
<div class="detail-value">${maintenance.deviceName}</div>
</div>
<div class="detail-item">
<div class="detail-label">保养类型</div>
<div class="detail-value">${maintenance.type}</div>
</div>
<div class="detail-item">
<div class="detail-label">计划时间</div>
<div class="detail-value">${maintenance.scheduledTime}</div>
</div>
<div class="detail-item">
<div class="detail-label">负责人</div>
<div class="detail-value">${maintenance.assignee}</div>
</div>
<div class="detail-item">
<div class="detail-label">当前状态</div>
<div class="detail-value">
<span class="status-badge ${getMaintenanceStatusClass(maintenance.status)}">
${getMaintenanceStatusName(maintenance.status)}
</span>
</div>
</div>
<div class="detail-item" style="grid-column: 1 / -1;">
<div class="detail-label">保养内容</div>
<div class="detail-value" style="min-height: 60px;">
${getMaintenanceContent(maintenance.type)}
</div>
</div>
`;
// 显示查看模态框
document.getElementById('viewMaintenanceModal').style.display = 'block';
}
// 关闭查看维护计划详情模态框
function closeViewMaintenanceModal() {
document.getElementById('viewMaintenanceModal').style.display = 'none';
}
// 辅助函数:获取维护状态名称
function getMaintenanceStatusName(status) {
const statusNames = {
'pending': '待执行',
'in_progress': '进行中',
'completed': '已完成'
};
return statusNames[status] || status;
}
// 辅助函数:获取维护状态类名
function getMaintenanceStatusClass(status) {
const statusClasses = {
'pending': 'status-maintenance',
'in_progress': 'status-online',
'completed': 'status-online'
};
return statusClasses[status] || '';
}
// 辅助函数:根据保养类型获取保养内容
function getMaintenanceContent(type) {
const contents = {
'routine': '1. 设备外观清洁<br>2. 电池检查与充电<br>3. 机械部件润滑<br>4. 功能测试',
'periodic': '1. 全面设备检查<br>2. 关键部件更换<br>3. 系统软件更新<br>4. 性能校准',
'condition': '1. 根据设备使用情况定制保养<br>2. 针对性部件检查<br>3. 预防性维护',
'emergency': '1. 故障诊断<br>2. 紧急维修<br>3. 安全评估'
};
return contents[type] || '根据设备实际情况制定具体保养内容';
}
// 查看故障维修详情
function viewRepair(id) {
const repair = repairData.find(r => r.repairId === id);
if (!repair) return;
// 填充查看模态框内容
const detailsContent = document.getElementById('repairDetailsContent');
detailsContent.innerHTML = `
<div class="detail-item">
<div class="detail-label">维修单号</div>
<div class="detail-value">${repair.repairId}</div>
</div>
<div class="detail-item">
<div class="detail-label">设备编号</div>
<div class="detail-value">${repair.deviceId}</div>
</div>
<div class="detail-item">
<div class="detail-label">设备名称</div>
<div class="detail-value">${getDeviceName(repair.deviceId)}</div>
</div>
<div class="detail-item">
<div class="detail-label">故障描述</div>
<div class="detail-value">${repair.fault}</div>
</div>
<div class="detail-item">
<div class="detail-label">报修人</div>
<div class="detail-value">${repair.reporter}</div>
</div>
<div class="detail-item">
<div class="detail-label">维修人员</div>
<div class="detail-value">${repair.repairer}</div>
</div>
<div class="detail-item">
<div class="detail-label">报修时间</div>
<div class="detail-value">${getRepairTime(repair.repairId)}</div>
</div>
<div class="detail-item">
<div class="detail-label">紧急程度</div>
<div class="detail-value">
<span class="status-badge ${getPriorityClass(repair.priority)}">
${getPriorityName(repair.priority)}
</span>
</div>
</div>
<div class="detail-item">
<div class="detail-label">当前状态</div>
<div class="detail-value">
<span class="status-badge ${getRepairStatusClass(repair.status)}">
${getRepairStatusName(repair.status)}
</span>
</div>
</div>
<div class="detail-item" style="grid-column: 1 / -1;">
<div class="detail-label">维修进度</div>
<div class="detail-value" style="min-height: 60px;">
${getRepairProgress(repair.status)}
</div>
</div>
`;
// 显示查看模态框
document.getElementById('viewRepairModal').style.display = 'block';
}
// 关闭查看故障维修详情模态框
function closeViewRepairModal() {
document.getElementById('viewRepairModal').style.display = 'none';
}
// 辅助函数:获取设备名称
function getDeviceName(deviceId) {
const device = devices.find(d => d.id === deviceId) ||
monitorData.find(d => d.id === deviceId);
return device ? device.name : '未知设备';
}
// 辅助函数:获取维修时间(模拟数据)
function getRepairTime(repairId) {
// 这里可以根据实际数据获取,现在使用模拟数据
const times = {
'R001': '2024-01-15 09:30',
'R002': '2024-01-14 14:15',
'R003': '2024-01-13 11:20'
};
return times[repairId] || new Date().toLocaleString();
}
// 辅助函数:获取紧急程度名称
function getPriorityName(priority) {
const priorityNames = {
'high': '紧急',
'medium': '一般',
'low': '低'
};
return priorityNames[priority] || priority;
}
// 辅助函数:获取紧急程度类名
function getPriorityClass(priority) {
const priorityClasses = {
'high': 'status-fault',
'medium': 'status-maintenance',
'low': 'status-online'
};
return priorityClasses[priority] || '';
}
// 辅助函数:获取维修状态名称
function getRepairStatusName(status) {
const statusNames = {
'pending': '待维修',
'in_progress': '维修中',
'completed': '已完成'
};
return statusNames[status] || status;
}
// 辅助函数:获取维修状态类名
function getRepairStatusClass(status) {
const statusClasses = {
'pending': 'status-maintenance',
'in_progress': 'status-online',
'completed': 'status-online'
};
return statusClasses[status] || '';
}
// 辅助函数:根据状态获取维修进度
function getRepairProgress(status) {
const progresses = {
'pending': '维修任务已创建,等待技术人员处理',
'in_progress': '技术人员已开始维修,正在进行故障诊断和修复',
'completed': '维修已完成,设备已恢复正常工作状态'
};
return progresses[status] || '维修状态未知';
}
</script>
</body>
</html>