Yolov/templates/demo/无人机多平台线索推送系统.html

1205 lines
43 KiB
HTML
Raw Blame History

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>
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Microsoft YaHei', 'Segoe UI', Arial, sans-serif;
}
:root {
--primary-color: #1890ff;
--primary-light: #40a9ff;
--primary-lighter: #69c0ff;
--fire-color: #ff4d4f;
--building-color: #faad14;
--environment-color: #52c41a;
--bg-color: #f0f8ff;
--card-bg: #ffffff;
--shadow-color: rgba(24, 144, 255, 0.1);
--border-color: #e6f7ff;
}
body {
background-color: var(--bg-color);
color: #1d3557;
min-height: 100vh;
padding: 20px;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
padding: 0 20px;
}
.title-section h1 {
font-size: 28px;
color: var(--primary-color);
margin-bottom: 8px;
}
.title-section .subtitle {
color: #666;
font-size: 16px;
}
.notification-badge {
background-color: var(--fire-color);
color: white;
padding: 6px 12px;
border-radius: 20px;
font-size: 14px;
font-weight: 500;
display: flex;
align-items: center;
gap: 6px;
}
/* 主内容区域 */
.main-container {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 25px;
max-width: 1600px;
margin: 0 auto;
}
/* 左侧内容 */
.left-content {
display: flex;
flex-direction: column;
gap: 25px;
}
/* 平台卡片 */
.platform-cards {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
margin-bottom: 20px;
}
.platform-card {
background-color: var(--card-bg);
border-radius: 12px;
padding: 25px;
box-shadow: 0 6px 16px var(--shadow-color);
transition: transform 0.3s, box-shadow 0.3s;
border-top: 5px solid transparent;
position: relative;
overflow: hidden;
}
.platform-card:hover {
transform: translateY(-5px);
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
}
.platform-card.fire-platform {
border-top-color: var(--fire-color);
}
.platform-card.building-platform {
border-top-color: var(--building-color);
}
.platform-card.environment-platform {
border-top-color: var(--environment-color);
}
.platform-card::before {
content: '';
position: absolute;
top: 0;
right: 0;
width: 60px;
height: 60px;
background: rgba(0, 0, 0, 0.03);
border-radius: 50%;
transform: translate(20px, -20px);
}
.platform-header {
display: flex;
align-items: center;
margin-bottom: 20px;
}
.platform-icon {
width: 50px;
height: 50px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
margin-right: 15px;
}
.fire-platform .platform-icon {
background-color: rgba(255, 77, 79, 0.1);
color: var(--fire-color);
}
.building-platform .platform-icon {
background-color: rgba(250, 173, 20, 0.1);
color: var(--building-color);
}
.environment-platform .platform-icon {
background-color: rgba(82, 196, 26, 0.1);
color: var(--environment-color);
}
.platform-info h3 {
font-size: 20px;
margin-bottom: 5px;
}
.platform-status {
font-size: 14px;
color: #666;
display: flex;
align-items: center;
gap: 6px;
}
.status-indicator {
width: 8px;
height: 8px;
border-radius: 50%;
background-color: #52c41a;
}
.status-indicator.offline {
background-color: #ff4d4f;
}
.platform-stats {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
}
.stat-item {
text-align: center;
}
.stat-value {
font-size: 24px;
font-weight: bold;
display: block;
}
.stat-label {
font-size: 12px;
color: #666;
margin-top: 5px;
}
.platform-actions {
display: flex;
gap: 10px;
}
.btn {
padding: 8px 16px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
font-weight: 500;
transition: all 0.3s;
flex: 1;
}
.btn-primary {
background-color: var(--primary-color);
color: white;
}
.btn-primary:hover {
background-color: var(--primary-light);
}
.btn-test {
background-color: #f0f0f0;
color: #333;
}
.btn-test:hover {
background-color: #e0e0e0;
}
/* 线索推送历史 */
.clue-history {
background-color: var(--card-bg);
border-radius: 12px;
padding: 25px;
box-shadow: 0 6px 16px var(--shadow-color);
}
.section-title {
font-size: 20px;
margin-bottom: 20px;
color: #1d3557;
display: flex;
align-items: center;
justify-content: space-between;
}
.history-table {
width: 100%;
border-collapse: collapse;
}
.history-table th {
text-align: left;
padding: 12px 15px;
border-bottom: 2px solid var(--border-color);
color: #666;
font-weight: 600;
font-size: 14px;
}
.history-table td {
padding: 15px;
border-bottom: 1px solid var(--border-color);
font-size: 14px;
}
.history-table tr:hover {
background-color: #f9fdff;
}
/* 状态标签 */
.status-badge {
padding: 4px 10px;
border-radius: 20px;
font-size: 12px;
font-weight: 500;
display: inline-block;
}
.status-success {
background-color: rgba(82, 196, 26, 0.1);
color: #52c41a;
}
.status-pending {
background-color: rgba(250, 173, 20, 0.1);
color: #faad14;
}
.status-failed {
background-color: rgba(255, 77, 79, 0.1);
color: #ff4d4f;
}
/* 右侧内容 */
.right-content {
display: flex;
flex-direction: column;
gap: 25px;
}
/* 推送配置 */
.push-config {
background-color: var(--card-bg);
border-radius: 12px;
padding: 25px;
box-shadow: 0 6px 16px var(--shadow-color);
}
.config-form {
display: flex;
flex-direction: column;
gap: 20px;
}
.form-group {
display: flex;
flex-direction: column;
gap: 8px;
}
.form-group label {
font-size: 14px;
font-weight: 500;
color: #333;
}
.form-group input, .form-group select {
padding: 10px 15px;
border: 1px solid #d9d9d9;
border-radius: 6px;
font-size: 14px;
transition: border-color 0.3s;
}
.form-group input:focus, .form-group select:focus {
outline: none;
border-color: var(--primary-color);
}
.checkbox-group {
display: flex;
flex-wrap: wrap;
gap: 15px;
margin-top: 10px;
}
.checkbox-item {
display: flex;
align-items: center;
gap: 8px;
}
/* 实时推送监控 */
.push-monitor {
background-color: var(--card-bg);
border-radius: 12px;
padding: 25px;
box-shadow: 0 6px 16px var(--shadow-color);
}
.monitor-chart {
height: 200px;
width: 100%;
}
/* 推送统计 */
.push-stats {
background-color: var(--card-bg);
border-radius: 12px;
padding: 25px;
box-shadow: 0 6px 16px var(--shadow-color);
}
.stats-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
margin-top: 15px;
}
.stat-card {
text-align: center;
padding: 20px;
border-radius: 10px;
background-color: #f9fdff;
}
.stat-card.fire-stat {
border-left: 4px solid var(--fire-color);
}
.stat-card.building-stat {
border-left: 4px solid var(--building-color);
}
.stat-card .stat-number {
font-size: 28px;
font-weight: bold;
margin-bottom: 5px;
}
.stat-card .stat-label {
font-size: 14px;
color: #666;
}
/* 模态框 */
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1000;
align-items: center;
justify-content: center;
}
.modal-content {
background-color: white;
border-radius: 12px;
padding: 30px;
width: 90%;
max-width: 600px;
max-height: 80vh;
overflow-y: auto;
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.modal-title {
font-size: 20px;
color: #1d3557;
}
.close-modal {
background: none;
border: none;
font-size: 24px;
cursor: pointer;
color: #999;
}
/* 响应式设计 */
@media (max-width: 1200px) {
.main-container {
grid-template-columns: 1fr;
}
}
@media (max-width: 768px) {
.platform-cards {
grid-template-columns: 1fr;
}
.header {
flex-direction: column;
gap: 15px;
align-items: flex-start;
}
.stats-grid {
grid-template-columns: 1fr;
}
}
/* 动画效果 */
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
.pulse {
animation: pulse 2s infinite;
}
/* 滚动条美化 */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 4px;
}
::-webkit-scrollbar-thumb {
background: var(--primary-light);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--primary-color);
}
</style>
</head>
<body>
<!-- 顶部导航 -->
<div class="header">
<div class="title-section">
<h1>无人机多平台线索推送系统</h1>
<div class="subtitle">智能识别结果自动分发至各业务平台</div>
</div>
<div class="notification-badge">
<span>📢</span>
<span id="unread-count">3条待处理线索</span>
</div>
</div>
<!-- 主内容区 -->
<div class="main-container">
<!-- 左侧内容 -->
<div class="left-content">
<!-- 平台卡片 -->
<div class="platform-cards">
<div class="platform-card fire-platform">
<div class="platform-header">
<div class="platform-icon">🔥</div>
<div class="platform-info">
<h3>防火监控平台</h3>
<div class="platform-status">
<span class="status-indicator"></span>
<span>连接正常</span>
</div>
</div>
</div>
<div class="platform-stats">
<div class="stat-item">
<span class="stat-value" id="fire-today">12</span>
<span class="stat-label">今日推送</span>
</div>
<div class="stat-item">
<span class="stat-value" id="fire-success">98%</span>
<span class="stat-label">成功率</span>
</div>
<div class="stat-item">
<span class="stat-value" id="fire-response">3.2s</span>
<span class="stat-label">平均响应</span>
</div>
</div>
<div class="platform-actions">
<button class="btn btn-primary" onclick="openPushModal('fire')">推送测试</button>
<button class="btn btn-test" onclick="viewPlatformDetails('fire')">查看详情</button>
</div>
</div>
<div class="platform-card building-platform">
<div class="platform-header">
<div class="platform-icon">🏗️</div>
<div class="platform-info">
<h3>违建监测平台</h3>
<div class="platform-status">
<span class="status-indicator"></span>
<span>连接正常</span>
</div>
</div>
</div>
<div class="platform-stats">
<div class="stat-item">
<span class="stat-value" id="building-today">8</span>
<span class="stat-label">今日推送</span>
</div>
<div class="stat-item">
<span class="stat-value" id="building-success">95%</span>
<span class="stat-label">成功率</span>
</div>
<div class="stat-item">
<span class="stat-value" id="building-response">4.5s</span>
<span class="stat-label">平均响应</span>
</div>
</div>
<div class="platform-actions">
<button class="btn btn-primary" onclick="openPushModal('building')">推送测试</button>
<button class="btn btn-test" onclick="viewPlatformDetails('building')">查看详情</button>
</div>
</div>
<div class="platform-card environment-platform">
<div class="platform-header">
<div class="platform-icon">🌳</div>
<div class="platform-info">
<h3>环保监测平台</h3>
<div class="platform-status">
<span class="status-indicator offline"></span>
<span>连接异常</span>
</div>
</div>
</div>
<div class="platform-stats">
<div class="stat-item">
<span class="stat-value" id="env-today">5</span>
<span class="stat-label">今日推送</span>
</div>
<div class="stat-item">
<span class="stat-value" id="env-success">87%</span>
<span class="stat-label">成功率</span>
</div>
<div class="stat-item">
<span class="stat-value" id="env-response">5.8s</span>
<span class="stat-label">平均响应</span>
</div>
</div>
<div class="platform-actions">
<button class="btn btn-primary" onclick="openPushModal('environment')">推送测试</button>
<button class="btn btn-test" onclick="reconnectPlatform('environment')">重新连接</button>
</div>
</div>
</div>
<!-- 线索推送历史 -->
<div class="clue-history">
<div class="section-title">
<span>最近推送记录</span>
<button class="btn btn-test" onclick="refreshHistory()">刷新</button>
</div>
<table class="history-table">
<thead>
<tr>
<th>时间</th>
<th>线索类型</th>
<th>目标平台</th>
<th>内容摘要</th>
<th>状态</th>
</tr>
</thead>
<tbody id="history-body">
<!-- 历史记录将通过JavaScript动态生成 -->
</tbody>
</table>
</div>
</div>
<!-- 右侧内容 -->
<div class="right-content">
<!-- 推送配置 -->
<div class="push-config">
<div class="section-title">推送规则配置</div>
<form class="config-form" id="push-config-form">
<div class="form-group">
<label for="clue-type">线索类型自动分发</label>
<select id="clue-type">
<option value="auto">智能自动分发</option>
<option value="manual">手动确认分发</option>
</select>
</div>
<div class="form-group">
<label>推送优先级设置</label>
<select id="priority-level">
<option value="high">高优先级(立即推送)</option>
<option value="normal" selected>普通优先级(批量推送)</option>
<option value="low">低优先级(定时推送)</option>
</select>
</div>
<div class="form-group">
<label>重试机制</label>
<div class="checkbox-group">
<label class="checkbox-item">
<input type="checkbox" id="retry-enable" checked>
<span>启用失败重试</span>
</label>
<label class="checkbox-item">
<input type="checkbox" id="alert-enable" checked>
<span>失败时告警</span>
</label>
</div>
</div>
<div class="form-group">
<label for="retry-count">最大重试次数</label>
<input type="number" id="retry-count" value="3" min="1" max="10">
</div>
<button type="button" class="btn btn-primary" onclick="saveConfig()">保存配置</button>
</form>
</div>
<!-- 实时推送监控 -->
<div class="push-monitor">
<div class="section-title">实时推送监控</div>
<div class="monitor-chart" id="monitor-chart"></div>
</div>
<!-- 推送统计 -->
<div class="push-stats">
<div class="section-title">今日推送统计</div>
<div class="stats-grid">
<div class="stat-card fire-stat">
<div class="stat-number" id="today-fire">12</div>
<div class="stat-label">防火线索</div>
</div>
<div class="stat-card building-stat">
<div class="stat-number" id="today-building">8</div>
<div class="stat-label">违建线索</div>
</div>
<div class="stat-card">
<div class="stat-number" id="success-rate">95%</div>
<div class="stat-label">推送成功率</div>
</div>
<div class="stat-card">
<div class="stat-number" id="avg-time">4.2s</div>
<div class="stat-label">平均响应时间</div>
</div>
</div>
</div>
</div>
</div>
<!-- 推送测试模态框 -->
<div class="modal" id="push-modal">
<div class="modal-content">
<div class="modal-header">
<div class="modal-title" id="modal-title">推送测试到防火平台</div>
<button class="close-modal" onclick="closeModal()">×</button>
</div>
<div id="modal-body">
<!-- 模态框内容将通过JavaScript动态生成 -->
</div>
</div>
</div>
<script>
// 模拟数据
const platformData = {
fire: {
name: "防火监控平台",
todayPush: 12,
successRate: 98,
avgResponse: 3.2,
endpoint: "https://fire-platform.example.com/api/clue",
status: "connected"
},
building: {
name: "违建监测平台",
todayPush: 8,
successRate: 95,
avgResponse: 4.5,
endpoint: "https://building-platform.example.com/api/report",
status: "connected"
},
environment: {
name: "环保监测平台",
todayPush: 5,
successRate: 87,
avgResponse: 5.8,
endpoint: "https://env-platform.example.com/api/alert",
status: "disconnected"
}
};
// 模拟推送历史数据
const pushHistory = [
{ time: "10:23:15", type: "火点检测", platform: "防火平台", content: "发现疑似火点,坐标: (116.397, 39.916)", status: "success" },
{ time: "10:15:42", type: "违建识别", platform: "违建平台", content: "发现新增违建面积约120㎡", status: "success" },
{ time: "10:08:33", type: "烟雾检测", platform: "防火平台", content: "发现异常烟雾置信度92%", status: "success" },
{ time: "09:56:21", type: "排污监测", platform: "环保平台", content: "发现污水排放,坐标: (116.401, 39.912)", status: "failed" },
{ time: "09:42:11", type: "违建识别", platform: "违建平台", content: "发现施工违建已持续3天", status: "success" },
{ time: "09:35:47", type: "火点检测", platform: "防火平台", content: "发现高温区域温度65℃", status: "pending" },
{ time: "09:22:18", type: "垃圾堆放", platform: "环保平台", content: "发现违规垃圾堆放点", status: "success" },
{ time: "09:10:05", type: "违建识别", platform: "违建平台", content: "发现扩建违建增加面积80㎡", status: "success" }
];
// 模拟线索类型
const clueTypes = [
{ id: 1, name: "火点检测", platform: "fire", icon: "🔥", color: "#ff4d4f" },
{ id: 2, name: "烟雾检测", platform: "fire", icon: "💨", color: "#ff4d4f" },
{ id: 3, name: "高温区域", platform: "fire", icon: "🌡️", color: "#ff4d4f" },
{ id: 4, name: "新增违建", platform: "building", icon: "🏗️", color: "#faad14" },
{ id: 5, name: "扩建违建", platform: "building", icon: "🔨", color: "#faad14" },
{ id: 6, name: "施工违建", platform: "building", icon: "🚧", color: "#faad14" },
{ id: 7, name: "排污监测", platform: "environment", icon: "🌊", color: "#52c41a" },
{ id: 8, name: "垃圾堆放", platform: "environment", icon: "🗑️", color: "#52c41a" },
{ id: 9, name: "水质异常", platform: "environment", icon: "💧", color: "#52c41a" }
];
// 初始化函数
function init() {
updatePlatformStats();
renderPushHistory();
initMonitorChart();
updateTodayStats();
// 模拟实时更新
setInterval(() => {
updateRealTimeData();
}, 3000);
}
// 更新平台统计信息
function updatePlatformStats() {
// 防火平台
document.getElementById('fire-today').textContent = platformData.fire.todayPush;
document.getElementById('fire-success').textContent = platformData.fire.successRate + '%';
document.getElementById('fire-response').textContent = platformData.fire.avgResponse + 's';
// 违建平台
document.getElementById('building-today').textContent = platformData.building.todayPush;
document.getElementById('building-success').textContent = platformData.building.successRate + '%';
document.getElementById('building-response').textContent = platformData.building.avgResponse + 's';
// 环保平台
document.getElementById('env-today').textContent = platformData.environment.todayPush;
document.getElementById('env-success').textContent = platformData.environment.successRate + '%';
document.getElementById('env-response').textContent = platformData.environment.avgResponse + 's';
}
// 渲染推送历史
function renderPushHistory() {
const historyBody = document.getElementById('history-body');
historyBody.innerHTML = '';
pushHistory.forEach(record => {
const row = document.createElement('tr');
// 状态标签
let statusBadge = '';
if (record.status === 'success') {
statusBadge = '<span class="status-badge status-success">成功</span>';
} else if (record.status === 'pending') {
statusBadge = '<span class="status-badge status-pending">处理中</span>';
} else {
statusBadge = '<span class="status-badge status-failed">失败</span>';
}
row.innerHTML = `
<td>${record.time}</td>
<td>${record.type}</td>
<td>${record.platform}</td>
<td>${record.content}</td>
<td>${statusBadge}</td>
`;
historyBody.appendChild(row);
});
}
// 初始化监控图表
function initMonitorChart() {
const chartDom = document.getElementById('monitor-chart');
const chart = echarts.init(chartDom);
const option = {
color: ['#1890ff', '#52c41a', '#faad14'],
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
top: '10%',
containLabel: true
},
legend: {
data: ['防火平台', '违建平台', '环保平台'],
textStyle: {
color: '#666'
},
top: 0
},
xAxis: {
type: 'category',
data: ['09:00', '10:00', '11:00', '12:00', '13:00', '14:00', '15:00'],
axisLine: {
lineStyle: {
color: '#d9d9d9'
}
}
},
yAxis: {
type: 'value',
name: '推送次数',
axisLine: {
lineStyle: {
color: '#d9d9d9'
}
}
},
series: [
{
name: '防火平台',
type: 'bar',
stack: 'total',
emphasis: {
focus: 'series'
},
data: [2, 4, 3, 5, 3, 4, 2]
},
{
name: '违建平台',
type: 'bar',
stack: 'total',
emphasis: {
focus: 'series'
},
data: [1, 2, 2, 3, 2, 3, 1]
},
{
name: '环保平台',
type: 'bar',
stack: 'total',
emphasis: {
focus: 'series'
},
data: [0, 1, 1, 2, 1, 2, 0]
}
]
};
chart.setOption(option);
// 响应式调整
window.addEventListener('resize', function() {
chart.resize();
});
}
// 更新今日统计
function updateTodayStats() {
// 计算今日总数
let totalFire = 0;
let totalBuilding = 0;
pushHistory.forEach(record => {
if (record.platform === '防火平台') {
totalFire++;
} else if (record.platform === '违建平台') {
totalBuilding++;
}
});
// 计算成功率
let successCount = 0;
pushHistory.forEach(record => {
if (record.status === 'success') {
successCount++;
}
});
const successRate = Math.round((successCount / pushHistory.length) * 100);
// 更新显示
document.getElementById('today-fire').textContent = totalFire;
document.getElementById('today-building').textContent = totalBuilding;
document.getElementById('success-rate').textContent = successRate + '%';
}
// 更新实时数据
function updateRealTimeData() {
// 模拟数据变化
const now = new Date();
const timeString = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`;
// 随机添加新的推送记录
if (Math.random() > 0.7 && pushHistory.length < 15) {
const types = ['火点检测', '烟雾检测', '新增违建', '排污监测'];
const platforms = ['防火平台', '违建平台', '环保平台'];
const statuses = ['success', 'pending', 'failed'];
const newRecord = {
time: timeString,
type: types[Math.floor(Math.random() * types.length)],
platform: platforms[Math.floor(Math.random() * platforms.length)],
content: '模拟推送测试数据,坐标: (116.' + (397 + Math.floor(Math.random() * 10)) + ', 39.' + (916 + Math.floor(Math.random() * 10)) + ')',
status: statuses[Math.floor(Math.random() * statuses.length)]
};
pushHistory.unshift(newRecord);
if (pushHistory.length > 10) pushHistory.pop();
renderPushHistory();
updateTodayStats();
// 更新未读数量
const unreadCount = pushHistory.filter(r => r.status === 'pending').length;
document.getElementById('unread-count').textContent = unreadCount + '条待处理线索';
}
}
// 打开推送测试模态框
function openPushModal(platformType) {
const modal = document.getElementById('push-modal');
const modalTitle = document.getElementById('modal-title');
const modalBody = document.getElementById('modal-body');
const platform = platformData[platformType];
modalTitle.textContent = `推送测试到${platform.name}`;
// 根据平台类型生成不同的测试内容
let testContent = '';
let testButtonText = '立即推送';
if (platformType === 'fire') {
testContent = `
<div style="margin-bottom: 20px;">
<h3 style="margin-bottom: 10px; color: #ff4d4f;">🔥 防火线索测试</h3>
<p style="color: #666; margin-bottom: 15px;">模拟推送一条防火线索到${platform.name}</p>
<div style="background-color: #f9fdff; padding: 15px; border-radius: 8px; margin-bottom: 20px;">
<p><strong>线索内容:</strong>发现疑似火点,坐标: (116.397128, 39.916527)</p>
<p><strong>置信度:</strong>92%</p>
<p><strong>温度:</strong>65℃</p>
<p><strong>推送端点:</strong>${platform.endpoint}</p>
</div>
</div>
`;
} else if (platformType === 'building') {
testContent = `
<div style="margin-bottom: 20px;">
<h3 style="margin-bottom: 10px; color: #faad14;">🏗️ 违建线索测试</h3>
<p style="color: #666; margin-bottom: 15px;">模拟推送一条违建线索到${platform.name}</p>
<div style="background-color: #f9fdff; padding: 15px; border-radius: 8px; margin-bottom: 20px;">
<p><strong>线索内容:</strong>发现新增违建面积约120㎡</p>
<p><strong>置信度:</strong>88%</p>
<p><strong>位置:</strong>XX区XX街道XX号</p>
<p><strong>推送端点:</strong>${platform.endpoint}</p>
</div>
</div>
`;
} else {
testContent = `
<div style="margin-bottom: 20px;">
<h3 style="margin-bottom: 10px; color: #52c41a;">🌳 环保线索测试</h3>
<p style="color: #666; margin-bottom: 15px;">模拟推送一条环保线索到${platform.name}</p>
<div style="background-color: #f9fdff; padding: 15px; border-radius: 8px; margin-bottom: 20px;">
<p><strong>线索内容:</strong>发现污水排放,坐标: (116.401, 39.912)</p>
<p><strong>置信度:</strong>85%</p>
<p><strong>排放类型:</strong>工业废水</p>
<p><strong>推送端点:</strong>${platform.endpoint}</p>
</div>
${platform.status === 'disconnected' ? '<div style="background-color: #fff2f0; padding: 10px; border-radius: 6px; margin-bottom: 15px; color: #ff4d4f; border: 1px solid #ffccc7;">⚠️ 当前平台连接异常,推送可能失败</div>' : ''}
</div>
`;
if (platform.status === 'disconnected') {
testButtonText = '尝试推送';
}
}
modalBody.innerHTML = testContent + `
<div style="display: flex; gap: 10px;">
<button class="btn btn-primary" style="flex: 1;" onclick="testPush('${platformType}')">${testButtonText}</button>
<button class="btn btn-test" style="flex: 1;" onclick="closeModal()">取消</button>
</div>
`;
modal.style.display = 'flex';
}
// 关闭模态框
function closeModal() {
document.getElementById('push-modal').style.display = 'none';
}
// 测试推送
function testPush(platformType) {
const platform = platformData[platformType];
// 模拟推送延迟
setTimeout(() => {
// 模拟成功或失败
const isSuccess = platform.status === 'connected' ? Math.random() > 0.3 : false;
if (isSuccess) {
alert(`✅ 推送测试成功!线索已发送到${platform.name}`);
// 更新统计数据
platform.todayPush++;
updatePlatformStats();
// 添加到历史记录
const now = new Date();
const timeString = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`;
let typeName = '';
let content = '';
if (platformType === 'fire') {
typeName = '火点检测';
content = '测试推送:发现疑似火点,坐标: (116.397, 39.916)';
} else if (platformType === 'building') {
typeName = '违建识别';
content = '测试推送发现新增违建面积约120㎡';
} else {
typeName = '排污监测';
content = '测试推送:发现污水排放,坐标: (116.401, 39.912)';
}
pushHistory.unshift({
time: timeString,
type: typeName,
platform: platform.name,
content: content,
status: 'success'
});
if (pushHistory.length > 10) pushHistory.pop();
renderPushHistory();
updateTodayStats();
} else {
alert(`❌ 推送测试失败!${platform.name}连接异常,请检查网络配置或平台状态。`);
// 添加到失败记录
const now = new Date();
const timeString = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`;
pushHistory.unshift({
time: timeString,
type: '连接测试',
platform: platform.name,
content: '平台连接测试失败',
status: 'failed'
});
if (pushHistory.length > 10) pushHistory.pop();
renderPushHistory();
}
closeModal();
}, 1000);
}
// 查看平台详情
function viewPlatformDetails(platformType) {
const platform = platformData[platformType];
alert(`📋 ${platform.name}详情\n\n` +
`接口端点: ${platform.endpoint}\n` +
`今日推送: ${platform.todayPush}\n` +
`推送成功率: ${platform.successRate}%\n` +
`平均响应时间: ${platform.avgResponse}\n` +
`连接状态: ${platform.status === 'connected' ? '正常' : '异常'}`);
}
// 重新连接平台
function reconnectPlatform(platformType) {
const platform = platformData[platformType];
// 模拟重新连接过程
setTimeout(() => {
platform.status = 'connected';
document.querySelector(`.${platformType}-platform .status-indicator`).classList.remove('offline');
document.querySelector(`.${platformType}-platform .platform-status span:nth-child(2)`).textContent = '连接正常';
alert(`${platform.name}重新连接成功!`);
}, 1500);
}
// 刷新历史记录
function refreshHistory() {
renderPushHistory();
alert('历史记录已刷新!');
}
// 保存配置
function saveConfig() {
const clueType = document.getElementById('clue-type').value;
const priority = document.getElementById('priority-level').value;
const retryCount = document.getElementById('retry-count').value;
alert(`✅ 配置已保存!\n\n` +
`线索分发模式: ${clueType === 'auto' ? '智能自动分发' : '手动确认分发'}\n` +
`推送优先级: ${priority === 'high' ? '高' : priority === 'normal' ? '普通' : '低'}\n` +
`最大重试次数: ${retryCount}`);
}
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', init);
// 点击模态框外部关闭
window.onclick = function(event) {
const modal = document.getElementById('push-modal');
if (event.target === modal) {
closeModal();
}
};
</script>
</body>
</html>