Compare commits
4 Commits
dc5ad9f5e1
...
b79f345ecc
| Author | SHA1 | Date | |
|---|---|---|---|
| b79f345ecc | |||
| 2def5338d9 | |||
| cd15aa75c3 | |||
| 73c02fa365 |
@ -304,13 +304,13 @@ pageEncoding="UTF-8"%>
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<!-- 全屏提示遮罩 -->
|
<!-- 全屏提示遮罩 -->
|
||||||
<div class="fullscreen-overlay" id="fullscreenOverlay" onclick="enterFullscreen()">
|
<!-- <div class="fullscreen-overlay" id="fullscreenOverlay" onclick="enterFullscreen()">
|
||||||
<div class="tip-content">
|
<div class="tip-content">
|
||||||
<div class="icon">🖥️</div>
|
<div class="icon">🖥️</div>
|
||||||
<h2>点击进入全屏展示</h2>
|
<h2>点击进入全屏展示</h2>
|
||||||
<p>按 ESC 键可退出全屏</p>
|
<p>按 ESC 键可退出全屏</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> -->
|
||||||
<div class="screen-container">
|
<div class="screen-container">
|
||||||
<div class="rank-module-container">
|
<div class="rank-module-container">
|
||||||
<!-- Statistics -->
|
<!-- Statistics -->
|
||||||
@ -360,7 +360,7 @@ pageEncoding="UTF-8"%>
|
|||||||
污水特性: <span id="sewageType">--</span>
|
污水特性: <span id="sewageType">--</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-item">
|
<div class="info-item">
|
||||||
当前排污量: <span id="dischargeVolume">--</span>
|
日排量: <span id="dischargeVolume">--</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-item">
|
<div class="info-item">
|
||||||
接入状态: <span id="connectionStatus">--</span>
|
接入状态: <span id="connectionStatus">--</span>
|
||||||
@ -382,7 +382,7 @@ pageEncoding="UTF-8"%>
|
|||||||
<div id="chartInstant" class="chart-content"></div>
|
<div id="chartInstant" class="chart-content"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-chart-box">
|
<div class="detail-chart-box">
|
||||||
<div class="chart-subtitle">累计流量历史曲线 (日差值 - 近14天)</div>
|
<div class="chart-subtitle">累计流量历史曲线 (近14天)</div>
|
||||||
<div id="chartCumulative" class="chart-content"></div>
|
<div id="chartCumulative" class="chart-content"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -405,6 +405,9 @@ pageEncoding="UTF-8"%>
|
|||||||
var allEnterprises = []; // All data for map
|
var allEnterprises = []; // All data for map
|
||||||
var currentFocusIndex = 0;
|
var currentFocusIndex = 0;
|
||||||
var rotationTimer = null;
|
var rotationTimer = null;
|
||||||
|
|
||||||
|
// 获取上下文路径
|
||||||
|
var contextPath = "<%=request.getContextPath()%>";
|
||||||
|
|
||||||
// 进入全屏函数
|
// 进入全屏函数
|
||||||
function enterFullscreen() {
|
function enterFullscreen() {
|
||||||
@ -464,20 +467,289 @@ pageEncoding="UTF-8"%>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// API请求函数
|
||||||
|
function apiRequest(url, params) {
|
||||||
|
console.log("API Request:", contextPath + url, params);
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
$.ajax({
|
||||||
|
url: contextPath + url,
|
||||||
|
type: "POST",
|
||||||
|
data: params || {},
|
||||||
|
success: function (data) {
|
||||||
|
resolve(data);
|
||||||
|
},
|
||||||
|
error: function (xhr, status, error) {
|
||||||
|
console.error("API Request Error:", url, error);
|
||||||
|
reject(error);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载企业数据(排污源)
|
||||||
|
function loadEnterpriseData() {
|
||||||
|
return apiRequest("/sparepart/sewage/getList.do", {
|
||||||
|
page: 1,
|
||||||
|
rows: 10,
|
||||||
|
sort: "displacement",
|
||||||
|
order: "asc",
|
||||||
|
unitId: '0533JS',
|
||||||
|
})
|
||||||
|
.then(function (data) {
|
||||||
|
var dataList = data;
|
||||||
|
if (typeof data === "string") {
|
||||||
|
try {
|
||||||
|
dataList = JSON.parse(data);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("解析企业数据失败:", e);
|
||||||
|
dataList = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var list = dataList.rows || [];
|
||||||
|
console.log("企业接口返回数据条数:", list.length);
|
||||||
|
|
||||||
|
if (!list || list.length === 0) {
|
||||||
|
console.error("!!! 企业接口返回数据为空!");
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统计接入状态
|
||||||
|
var total = dataList.total;
|
||||||
|
var connected = 0;
|
||||||
|
var connecting = 0;
|
||||||
|
|
||||||
|
var enterprises = list.map(function (item, idx) {
|
||||||
|
// 解析经纬度
|
||||||
|
var lng = null, lat = null;
|
||||||
|
if (item.longitudeLatitude) {
|
||||||
|
var coords = String(item.longitudeLatitude).split(",");
|
||||||
|
if (coords.length >= 2) {
|
||||||
|
lng = parseFloat(coords[0]);
|
||||||
|
lat = parseFloat(coords[1]);
|
||||||
|
} else if (coords.length === 1) {
|
||||||
|
lng = parseFloat(coords[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 从 company 对象获取经纬度
|
||||||
|
if ((!lng || !lat) && item.company) {
|
||||||
|
lng = lng || item.company.longitude;
|
||||||
|
lat = lat || item.company.latitude;
|
||||||
|
}
|
||||||
|
// 默认位置
|
||||||
|
if (!lng || !lat) {
|
||||||
|
lng = 121.3 + idx * 0.01;
|
||||||
|
lat = 30.7 + idx * 0.005;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析日排量数值
|
||||||
|
var dischargeValue = 0;
|
||||||
|
if (item.displacement) {
|
||||||
|
dischargeValue = parseFloat(item.displacement) || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 接入状态判断(根据已关联点位和已录入数据)
|
||||||
|
var hasPoint = item._point ? true : false;
|
||||||
|
var hasInput = item._input ? true : false;
|
||||||
|
var connectionStatus = "接入中";
|
||||||
|
if (hasPoint || hasInput) {
|
||||||
|
connectionStatus = "已接入";
|
||||||
|
connected++;
|
||||||
|
} else {
|
||||||
|
connecting++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 所属行业作为污水特性
|
||||||
|
var sewageTypes = ["化学需氧量", "氨氮", "总磷", "重金属", "酸碱废水"];
|
||||||
|
var sewageType = item.trade || sewageTypes[idx % sewageTypes.length];
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: item.id,
|
||||||
|
contractNumber: item.contractNumber || "",
|
||||||
|
name: item.name || "企业-" + (idx + 1),
|
||||||
|
value: dischargeValue,
|
||||||
|
sewageType: sewageType,
|
||||||
|
connectionStatus: connectionStatus,
|
||||||
|
address: item.address || "",
|
||||||
|
areaName: item.company ? item.company.name || "" : "",
|
||||||
|
processSectionName: item.processSection ? item.processSection.name || "" : "",
|
||||||
|
permitNum: item.permitNum || "",
|
||||||
|
// ventNum: item.ventNum || "", // 排放编号,用于流量接口
|
||||||
|
ventNum: 'DEV067' || "", // 排放编号,用于流量接口
|
||||||
|
trade: item.trade || "",
|
||||||
|
displacement: item.displacement ? item.displacement + "吨/天" : "-",
|
||||||
|
indicator: dischargeValue > 8000 ? "超级" : "普通",
|
||||||
|
photo: contextPath + "/IMG/login/company.png",
|
||||||
|
x: Math.random() * 90 + 5,
|
||||||
|
y: Math.random() * 80 + 10,
|
||||||
|
lng: lng,
|
||||||
|
lat: lat,
|
||||||
|
instantHistory: [], // 瞬时流量历史数据,后续通过接口获取
|
||||||
|
cumulativeHistory: [], // 累计流量历史数据,后续通过接口获取
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("企业数据处理后条数:", enterprises.length, "已接入:", connected, "接入中:", connecting);
|
||||||
|
|
||||||
|
// 更新统计数字
|
||||||
|
$("#totalCount").html(total + '<span class="stat-unit">家</span>');
|
||||||
|
$("#connectedCount").html(connected + '<span class="stat-unit">家</span>');
|
||||||
|
$("#connectingCount").html(connecting + '<span class="stat-unit">家</span>');
|
||||||
|
|
||||||
|
return enterprises;
|
||||||
|
})
|
||||||
|
.catch(function (err) {
|
||||||
|
console.error("加载企业数据失败:", err);
|
||||||
|
return [];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化日期时间 yyyy-MM-dd HH:mm
|
||||||
|
function formatDateTime(date) {
|
||||||
|
var year = date.getFullYear();
|
||||||
|
var month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
var day = String(date.getDate()).padStart(2, '0');
|
||||||
|
var hours = String(date.getHours()).padStart(2, '0');
|
||||||
|
var minutes = String(date.getMinutes()).padStart(2, '0');
|
||||||
|
return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载流量数据
|
||||||
|
// type: 'instant' 瞬时流量(近3天), 'cumulative' 累计流量(近14天)
|
||||||
|
function loadFlowData(ventNum, type) {
|
||||||
|
if (!ventNum) {
|
||||||
|
console.warn("[loadFlowData] ventNum 为空,无法加载流量数据");
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
var mpcode, days;
|
||||||
|
if (type === 'instant') {
|
||||||
|
mpcode = ventNum + '_LJLL'; // 瞬时流量
|
||||||
|
days = 3;
|
||||||
|
} else {
|
||||||
|
mpcode = ventNum + '_LJLL'; // 累计流量
|
||||||
|
days = 14;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算日期范围
|
||||||
|
var now = new Date();
|
||||||
|
var edt = formatDateTime(now);
|
||||||
|
var startDate = new Date(now.getTime() - days * 24 * 60 * 60 * 1000);
|
||||||
|
var sdt = formatDateTime(startDate);
|
||||||
|
|
||||||
|
console.log("[loadFlowData] mpcode:", mpcode, "sdt:", sdt, "edt:", edt, "type:", type);
|
||||||
|
|
||||||
|
return apiRequest("/data/getDetailData.do", {
|
||||||
|
mpcode: mpcode,
|
||||||
|
sdt: sdt,
|
||||||
|
edt: edt
|
||||||
|
})
|
||||||
|
.then(function (data) {
|
||||||
|
console.log("[loadFlowData] 接口返回数据:", mpcode, data);
|
||||||
|
|
||||||
|
var dataList = data;
|
||||||
|
if (typeof data === 'string') {
|
||||||
|
try {
|
||||||
|
dataList = JSON.parse(data);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("[loadFlowData] 解析数据失败:", e);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取数值数组
|
||||||
|
var values = [];
|
||||||
|
if (Array.isArray(dataList)) {
|
||||||
|
dataList.forEach(function (item) {
|
||||||
|
// 假设返回数据格式为 [{time: xxx, value: xxx}, ...]
|
||||||
|
// 或者 [value1, value2, ...]
|
||||||
|
if (item.value !== undefined) {
|
||||||
|
values.push(parseFloat(item.value) || 0);
|
||||||
|
} else if (typeof item === 'number') {
|
||||||
|
values.push(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("[loadFlowData] 解析后数据条数:", values.length);
|
||||||
|
return values;
|
||||||
|
})
|
||||||
|
.catch(function (err) {
|
||||||
|
console.error("[loadFlowData] 请求失败:", mpcode, err);
|
||||||
|
return [];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 并行加载企业的瞬时和累计流量数据
|
||||||
|
function loadEnterpriseFlowData(enterprise) {
|
||||||
|
console.log("[loadEnterpriseFlowData] 加载企业流量数据:", enterprise.name, "ventNum:", enterprise.ventNum);
|
||||||
|
|
||||||
|
if (!enterprise.ventNum) {
|
||||||
|
console.warn("[loadEnterpriseFlowData] 企业 ventNum 为空,使用模拟数据");
|
||||||
|
enterprise.instantHistory = generateHistoryData(72); // 近3天小时数据
|
||||||
|
enterprise.cumulativeHistory = generateHistoryData(14); // 近14天数据
|
||||||
|
return Promise.resolve(enterprise);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.all([
|
||||||
|
loadFlowData(enterprise.ventNum, 'instant'),
|
||||||
|
loadFlowData(enterprise.ventNum, 'cumulative')
|
||||||
|
])
|
||||||
|
.then(function (results) {
|
||||||
|
enterprise.instantHistory = results[0].length > 0 ? results[0] : generateHistoryData(72); // 近3天小时数据
|
||||||
|
enterprise.cumulativeHistory = results[1].length > 0 ? results[1] : generateHistoryData(14); // 近14天数据
|
||||||
|
console.log("[loadEnterpriseFlowData] 流量数据加载完成:", enterprise.name,
|
||||||
|
"瞬时:", enterprise.instantHistory.length, "累计:", enterprise.cumulativeHistory.length);
|
||||||
|
return enterprise;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function initData() {
|
function initData() {
|
||||||
// Stats
|
// Init Charts first
|
||||||
|
myChartInstant = echarts.init(document.getElementById("chartInstant"));
|
||||||
|
myChartCumulative = echarts.init(
|
||||||
|
document.getElementById("chartCumulative"),
|
||||||
|
);
|
||||||
|
myChartRanking = echarts.init(document.getElementById("chartRanking"));
|
||||||
|
|
||||||
|
// 并行加载企业数据(用于统计和地图)和排行数据
|
||||||
|
Promise.all([
|
||||||
|
loadEnterpriseData(),
|
||||||
|
loadRankingData()
|
||||||
|
])
|
||||||
|
.then(function (results) {
|
||||||
|
var enterprises = results[0];
|
||||||
|
var rankingData = results[1];
|
||||||
|
|
||||||
|
if (!enterprises || enterprises.length === 0) {
|
||||||
|
console.warn("企业数据为空,使用默认模拟数据");
|
||||||
|
// enterprises = generateMockData();
|
||||||
|
enterprises = []
|
||||||
|
}
|
||||||
|
|
||||||
|
allEnterprises = enterprises;
|
||||||
|
|
||||||
|
// 渲染地图点位
|
||||||
|
// renderMapPoints();
|
||||||
|
|
||||||
|
// Start Loops - 每10秒刷新排行数据
|
||||||
|
startDataSimulation();
|
||||||
|
startRotation();
|
||||||
|
})
|
||||||
|
.catch(function (err) {
|
||||||
|
console.error("初始化数据失败:", err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成模拟数据(作为备用)
|
||||||
|
function generateMockData() {
|
||||||
var total = 158;
|
var total = 158;
|
||||||
var connected = 124;
|
var connected = 124;
|
||||||
var connecting = 34;
|
var connecting = 34;
|
||||||
$("#totalCount").html(total + '<span class="stat-unit">家</span>');
|
$("#totalCount").html(total + '<span class="stat-unit">家</span>');
|
||||||
$("#connectedCount").html(
|
$("#connectedCount").html(connected + '<span class="stat-unit">家</span>');
|
||||||
connected + '<span class="stat-unit">家</span>',
|
$("#connectingCount").html(connecting + '<span class="stat-unit">家</span>');
|
||||||
);
|
|
||||||
$("#connectingCount").html(
|
|
||||||
connecting + '<span class="stat-unit">家</span>',
|
|
||||||
);
|
|
||||||
|
|
||||||
// Generate Enterprises with Details
|
|
||||||
var enterprises = [];
|
var enterprises = [];
|
||||||
var sewageTypes = ["化学需氧量", "氨氮", "总磷", "重金属", "酸碱废水"];
|
var sewageTypes = ["化学需氧量", "氨氮", "总磷", "重金属", "酸碱废水"];
|
||||||
var connectionStatuses = ["已接入", "接入中"];
|
var connectionStatuses = ["已接入", "接入中"];
|
||||||
@ -488,47 +760,17 @@ pageEncoding="UTF-8"%>
|
|||||||
id: i,
|
id: i,
|
||||||
name: "企业-" + i,
|
name: "企业-" + i,
|
||||||
value: val,
|
value: val,
|
||||||
// Details
|
sewageType: sewageTypes[Math.floor(Math.random() * sewageTypes.length)],
|
||||||
sewageType:
|
connectionStatus: connectionStatuses[Math.floor(Math.random() * connectionStatuses.length)],
|
||||||
sewageTypes[Math.floor(Math.random() * sewageTypes.length)],
|
|
||||||
connectionStatus:
|
|
||||||
connectionStatuses[
|
|
||||||
Math.floor(Math.random() * connectionStatuses.length)
|
|
||||||
],
|
|
||||||
indicator: val > 8000 ? "超级" : "普通",
|
indicator: val > 8000 ? "超级" : "普通",
|
||||||
photo: "<%=request.getContextPath()%>/IMG/login/company.png", // Placeholder
|
photo: contextPath + "/IMG/login/company.png",
|
||||||
// Map Coordinates (Relative % in map container)
|
x: Math.random() * 90 + 5,
|
||||||
x: Math.random() * 90 + 5, // 5% to 95%
|
y: Math.random() * 80 + 10,
|
||||||
y: Math.random() * 80 + 10, // 10% to 90%
|
instantHistory: generateHistoryData(72),
|
||||||
// History Data
|
cumulativeHistory: generateHistoryData(14),
|
||||||
instantHistory: generateHistoryData(72), // 3 days * 24 hours
|
|
||||||
cumulativeHistory: generateHistoryData(14), // 14 days
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
allEnterprises = enterprises;
|
return enterprises;
|
||||||
|
|
||||||
// Init Charts
|
|
||||||
myChartInstant = echarts.init(document.getElementById("chartInstant"));
|
|
||||||
myChartCumulative = echarts.init(
|
|
||||||
document.getElementById("chartCumulative"),
|
|
||||||
);
|
|
||||||
myChartRanking = echarts.init(document.getElementById("chartRanking"));
|
|
||||||
// myNewBarChart = echarts.init(document.getElementById('newBarChart'));
|
|
||||||
|
|
||||||
// renderNewBarChart();
|
|
||||||
|
|
||||||
// Initial Sort
|
|
||||||
updateSortedData(enterprises);
|
|
||||||
|
|
||||||
// Render Lists & Map
|
|
||||||
renderRankingChart();
|
|
||||||
renderMapPoints();
|
|
||||||
|
|
||||||
updateDetailView();
|
|
||||||
|
|
||||||
// Start Loops
|
|
||||||
startDataSimulation(enterprises);
|
|
||||||
startRotation();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateHistoryData(count) {
|
function generateHistoryData(count) {
|
||||||
@ -872,38 +1114,106 @@ pageEncoding="UTF-8"%>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function startDataSimulation(enterprises) {
|
// 加载排行数据(最大和最小分别调用接口)
|
||||||
setInterval(function () {
|
function loadRankingData() {
|
||||||
// Randomize values
|
console.log("=== loadRankingData 开始加载排行数据 ===");
|
||||||
enterprises.forEach((item) => {
|
|
||||||
item.value += Math.floor(Math.random() * 200) - 100;
|
// 并行请求最大和最小排行数据
|
||||||
if (item.value < 0) item.value = 0;
|
var maxPromise = apiRequest("/sparepart/sewage/getList.do", {
|
||||||
item.indicator = item.value > 8000 ? "超级" : "普通";
|
page: 1,
|
||||||
|
rows: 10,
|
||||||
// Update Map Point Style
|
sort: "displacement",
|
||||||
var el = $("#point-" + item.id);
|
order: "desc",
|
||||||
if (item.value > 8000) {
|
unitId: '0533JS',
|
||||||
el.addClass("super");
|
});
|
||||||
} else {
|
|
||||||
el.removeClass("super");
|
var minPromise = apiRequest("/sparepart/sewage/getList.do", {
|
||||||
|
page: 1,
|
||||||
|
rows: 10,
|
||||||
|
sort: "displacement",
|
||||||
|
order: "asc",
|
||||||
|
unitId: '0533JS',
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise.all([maxPromise, minPromise])
|
||||||
|
.then(function (results) {
|
||||||
|
console.log("=== loadRankingData 接口返回 ===");
|
||||||
|
console.log("[最大排行数据]:", results[0]);
|
||||||
|
console.log("[最小排行数据]:", results[1]);
|
||||||
|
|
||||||
|
var maxData = results[0];
|
||||||
|
var minData = results[1];
|
||||||
|
|
||||||
|
// 解析最大排行数据
|
||||||
|
if (typeof maxData === "string") {
|
||||||
|
try { maxData = JSON.parse(maxData); } catch (e) { maxData = {}; }
|
||||||
}
|
}
|
||||||
el.find(".map-tooltip").html(
|
var maxList = maxData.rows || [];
|
||||||
item.name + "<br>排污量: " + item.value,
|
|
||||||
);
|
// 解析最小排行数据
|
||||||
|
if (typeof minData === "string") {
|
||||||
|
try { minData = JSON.parse(minData); } catch (e) { minData = {}; }
|
||||||
|
}
|
||||||
|
var minList = minData.rows || [];
|
||||||
|
|
||||||
|
console.log("最大排行条数:", maxList.length, "最小排行条数:", minList.length);
|
||||||
|
|
||||||
|
// 转换最大排行数据
|
||||||
|
currentMaxData = maxList.map(function (item, idx) {
|
||||||
|
var dischargeValue = parseFloat(item.displacement) || 0;
|
||||||
|
return {
|
||||||
|
id: item.id,
|
||||||
|
name: item.name || "企业-" + (idx + 1),
|
||||||
|
value: dischargeValue,
|
||||||
|
ventNum: item.ventNum || "", // 排放编号,用于流量接口
|
||||||
|
sewageType: item.trade || "-",
|
||||||
|
connectionStatus: item._point || item._input ? "已接入" : "接入中",
|
||||||
|
displacement: item.displacement ? item.displacement + "吨/天" : "-",
|
||||||
|
instantHistory: [],
|
||||||
|
cumulativeHistory: [],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// 转换最小排行数据
|
||||||
|
currentMinData = minList.map(function (item, idx) {
|
||||||
|
var dischargeValue = parseFloat(item.displacement) || 0;
|
||||||
|
return {
|
||||||
|
id: item.id,
|
||||||
|
name: item.name || "企业-" + (idx + 1),
|
||||||
|
value: dischargeValue,
|
||||||
|
ventNum: item.ventNum || "", // 排放编号,用于流量接口
|
||||||
|
sewageType: item.trade || "-",
|
||||||
|
connectionStatus: item._point || item._input ? "已接入" : "接入中",
|
||||||
|
displacement: item.displacement ? item.displacement + "吨/天" : "-",
|
||||||
|
instantHistory: [],
|
||||||
|
cumulativeHistory: [],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("[loadRankingData] 最大排行处理完成:", currentMaxData.length, "条");
|
||||||
|
console.log("[loadRankingData] 最小排行处理完成:", currentMinData.length, "条");
|
||||||
|
|
||||||
|
// 更新排行图表
|
||||||
|
renderRankingChart();
|
||||||
|
|
||||||
|
// 更新详情视图
|
||||||
|
if (currentMaxData.length > 0) {
|
||||||
|
updateDetailView();
|
||||||
|
}
|
||||||
|
|
||||||
|
return { max: currentMaxData, min: currentMinData };
|
||||||
|
})
|
||||||
|
.catch(function (err) {
|
||||||
|
console.error("加载排行数据失败:", err);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
updateSortedData(enterprises);
|
function startDataSimulation() {
|
||||||
renderRankingChart();
|
// 每10秒调用接口更新排行数据
|
||||||
// Update map tooltips if needed? Or just let them be static until hover re-render?
|
setInterval(function () {
|
||||||
// Re-rendering map points entirely is heavy if DOM is large, but 50 is fine.
|
console.log("[定时刷新] 开始刷新排行数据...");
|
||||||
// However, re-rendering loses hover state. Better to update text.
|
loadRankingData();
|
||||||
// For demo simplicity, we skip real-time map value update or do it simply:
|
}, 100000);
|
||||||
/*
|
|
||||||
enterprises.forEach(item => {
|
|
||||||
$('#point-' + item.id + ' .map-tooltip').html(item.name + '<br>排污量: ' + item.value);
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
}, 10000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function startRotation() {
|
function startRotation() {
|
||||||
@ -934,22 +1244,46 @@ pageEncoding="UTF-8"%>
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderDetailContent(enterprise) {
|
function renderDetailContent(enterprise) {
|
||||||
|
console.log("[renderDetailContent] 渲染企业详情:", enterprise.name, enterprise);
|
||||||
// Update DOM
|
// Update DOM
|
||||||
$("#detailTitle").text(enterprise.name);
|
$("#detailTitle").text(enterprise.name);
|
||||||
$("#sewageType").text(enterprise.sewageType);
|
$("#sewageType").text(enterprise.sewageType || "-");
|
||||||
$("#dischargeVolume").text(enterprise.value + " m³");
|
// 使用日排量字段,如果有 displacement 显示 displacement,否则显示 value
|
||||||
$("#connectionStatus").text(enterprise.connectionStatus);
|
$("#dischargeVolume").text(enterprise.displacement || (enterprise.value + " 吨/天"));
|
||||||
|
$("#connectionStatus").text(enterprise.connectionStatus || "-");
|
||||||
|
|
||||||
renderDetailCharts(enterprise);
|
// 加载流量数据并渲染图表
|
||||||
|
loadEnterpriseFlowData(enterprise).then(function (ent) {
|
||||||
|
renderDetailCharts(ent);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderDetailCharts(enterprise) {
|
function renderDetailCharts(enterprise) {
|
||||||
// Generate X labels
|
console.log("[renderDetailCharts] 渲染图表, 瞬时数据:", enterprise.instantHistory?.length, "累计数据:", enterprise.cumulativeHistory?.length);
|
||||||
|
|
||||||
|
// 根据实际数据长度动态生成 X 轴标签
|
||||||
|
var instantData = enterprise.instantHistory || [];
|
||||||
|
var cumulativeData = enterprise.cumulativeHistory || [];
|
||||||
|
|
||||||
|
// 瞬时流量 X 轴标签(按小时)
|
||||||
var hours = [];
|
var hours = [];
|
||||||
for (var i = 0; i < 72; i++) hours.push(i + "h");
|
for (var i = 0; i < instantData.length; i++) {
|
||||||
|
hours.push(i + "h");
|
||||||
|
}
|
||||||
|
// 如果没有数据,默认显示 3 天(近3天小时数据)
|
||||||
|
if (hours.length === 0) {
|
||||||
|
for (var i = 0; i < 72; i++) hours.push(i + "h");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 累计流量 X 轴标签(按天)
|
||||||
var days = [];
|
var days = [];
|
||||||
for (var j = 0; j < 14; j++) days.push("D" + (j + 1));
|
for (var j = 0; j < cumulativeData.length; j++) {
|
||||||
|
days.push("D" + (j + 1));
|
||||||
|
}
|
||||||
|
// 如果没有数据,默认显示 14 天
|
||||||
|
if (days.length === 0) {
|
||||||
|
for (var j = 0; j < 14; j++) days.push("D" + (j + 1));
|
||||||
|
}
|
||||||
|
|
||||||
// Instant Chart (Line)
|
// Instant Chart (Line)
|
||||||
var optionInstant = {
|
var optionInstant = {
|
||||||
@ -989,7 +1323,7 @@ pageEncoding="UTF-8"%>
|
|||||||
]),
|
]),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data: enterprise.instantHistory,
|
data: instantData.length > 0 ? instantData : generateHistoryData(72),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@ -1022,7 +1356,7 @@ pageEncoding="UTF-8"%>
|
|||||||
itemStyle: {
|
itemStyle: {
|
||||||
normal: { color: "#ffaa00", barBorderRadius: [5, 5, 0, 0] },
|
normal: { color: "#ffaa00", barBorderRadius: [5, 5, 0, 0] },
|
||||||
},
|
},
|
||||||
data: enterprise.cumulativeHistory,
|
data: cumulativeData.length > 0 ? cumulativeData : generateHistoryData(14),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
186
src/main/webapp/jsp/z_bigScreen/geo.html
Normal file
186
src/main/webapp/jsp/z_bigScreen/geo.html
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>天地图-金山卫雨污水管可视化(GeoJSON版)</title>
|
||||||
|
<!-- 引入天地图4.0 API(替换成你的Key) -->
|
||||||
|
<script type="text/javascript" src="https://api.tianditu.gov.cn/api?v=4.0&tk=f423193014cde7bf44b224c6ab2b1210"></script>
|
||||||
|
<style>
|
||||||
|
/* 地图容器 */
|
||||||
|
#map {
|
||||||
|
width: 100%;
|
||||||
|
height: 800px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
/* 图例样式 */
|
||||||
|
.legend {
|
||||||
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
right: 20px;
|
||||||
|
background: #ffffff;
|
||||||
|
padding: 10px 15px;
|
||||||
|
border: 1px solid #cccccc;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 14px;
|
||||||
|
box-shadow: 0 2px 6px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
.legend-title {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
.legend-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
.legend-color {
|
||||||
|
display: inline-block;
|
||||||
|
width: 15px;
|
||||||
|
height: 4px;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="map"></div>
|
||||||
|
<!-- 图例 -->
|
||||||
|
<div class="legend">
|
||||||
|
<div class="legend-title">雨污水管图例</div>
|
||||||
|
<div class="legend-item">
|
||||||
|
<span class="legend-color" style="background: #8B4513; width: 6px;"></span>DN300 污水管
|
||||||
|
</div>
|
||||||
|
<div class="legend-item">
|
||||||
|
<span class="legend-color" style="background: #8B4513; width: 8px;"></span>DN500 污水管
|
||||||
|
</div>
|
||||||
|
<div class="legend-item">
|
||||||
|
<span class="legend-color" style="background: #1E90FF; width: 5px;"></span>DN200 雨水管
|
||||||
|
</div>
|
||||||
|
<div class="legend-item">
|
||||||
|
<span class="legend-color" style="background: #1E90FF; width: 7px;"></span>DN400 雨水管
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// ===================== 基础配置 =====================
|
||||||
|
// 天地图中心点(金山卫区域)
|
||||||
|
const MAP_CENTER = [121.357888, 30.813165];
|
||||||
|
// 地图缩放级别(16为厂区级,可调整)
|
||||||
|
const MAP_ZOOM = 16;
|
||||||
|
// GeoJSON文件路径(本地/服务器路径,重点!)
|
||||||
|
const GEOJSON_PATH = "pipeline_data.geojson"; // 替换为你的GeoJSON文件路径
|
||||||
|
|
||||||
|
// ===================== 初始化地图 =====================
|
||||||
|
// 创建地图实例
|
||||||
|
var map = new T.Map('map');
|
||||||
|
// 设置中心点和缩放级别
|
||||||
|
map.centerAndZoom(new T.LngLat(MAP_CENTER[0], MAP_CENTER[1]), MAP_ZOOM);
|
||||||
|
// 开启鼠标滚轮缩放
|
||||||
|
map.enableScrollWheelZoom(true);
|
||||||
|
// 添加天地图底图(矢量+注记)
|
||||||
|
var vecLayer = new T.TileLayer("vec_w", {minZoom: 1, maxZoom: 18});
|
||||||
|
var cvaLayer = new T.TileLayer("cva_w", {minZoom: 1, maxZoom: 18});
|
||||||
|
map.addLayer(vecLayer);
|
||||||
|
map.addLayer(cvaLayer);
|
||||||
|
|
||||||
|
// ===================== 加载GeoJSON并渲染 =====================
|
||||||
|
// 加载本地GeoJSON文件
|
||||||
|
fetch(GEOJSON_PATH)
|
||||||
|
.then(response => {
|
||||||
|
// 检查文件加载是否成功
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`GeoJSON文件加载失败:${response.status} ${response.statusText}`);
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(geoJsonData => {
|
||||||
|
console.log("✅ GeoJSON数据加载成功", geoJsonData);
|
||||||
|
|
||||||
|
// 创建GeoJSON图层
|
||||||
|
var geoJsonLayer = new T.GeoJSONLayer(geoJsonData, {
|
||||||
|
// 自定义管道样式
|
||||||
|
style: function(feature) {
|
||||||
|
// 获取管道属性(根据你的GeoJSON字段调整)
|
||||||
|
var layerName = (feature.properties.LAYER || feature.properties.layer || "").toLowerCase();
|
||||||
|
var pipeSize = feature.properties.SIZE || feature.properties.pipe_size || "DN300";
|
||||||
|
|
||||||
|
// 按类型设置颜色:污水管-棕色,雨水管-蓝色
|
||||||
|
var color = "#8B4513"; // 默认污水管颜色
|
||||||
|
if (layerName.includes("雨水") || layerName.includes("rain")) {
|
||||||
|
color = "#1E90FF"; // 雨水管颜色
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按管径设置线宽
|
||||||
|
var weight = 6; // 默认DN300线宽
|
||||||
|
switch (pipeSize) {
|
||||||
|
case "DN200": weight = 5; break;
|
||||||
|
case "DN400": weight = 7; break;
|
||||||
|
case "DN500": weight = 8; break;
|
||||||
|
default: weight = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
color: color, // 管道颜色
|
||||||
|
weight: weight, // 线宽(对应管径)
|
||||||
|
opacity: 0.8, // 透明度
|
||||||
|
lineJoin: "round" // 折线拐角圆角
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 将GeoJSON图层添加到地图
|
||||||
|
map.addOverLay(geoJsonLayer);
|
||||||
|
|
||||||
|
// ===================== 交互功能 =====================
|
||||||
|
// 1. 点击管道显示详情弹窗
|
||||||
|
geoJsonLayer.addEventListener("click", function(e) {
|
||||||
|
// 获取管道属性
|
||||||
|
var props = e.feature.properties;
|
||||||
|
var layerName = props.LAYER || props.layer || "未知图层";
|
||||||
|
var pipeSize = props.SIZE || props.pipe_size || "未知管径";
|
||||||
|
var pipeId = props.pipe_id || props.id || "未知ID";
|
||||||
|
var coord = `${e.lnglat.getLng().toFixed(6)}, ${e.lnglat.getLat().toFixed(6)}`;
|
||||||
|
|
||||||
|
// 创建弹窗
|
||||||
|
var infoWindow = new T.InfoWindow();
|
||||||
|
infoWindow.setContent(`
|
||||||
|
<div style="padding: 10px; min-width: 200px; font-size: 14px;">
|
||||||
|
<strong style="font-size: 15px;">管道详情</strong><hr style="margin: 5px 0; border: 0; border-top: 1px solid #eee;">
|
||||||
|
<div>管道ID:${pipeId}</div>
|
||||||
|
<div>图层名称:${layerName}</div>
|
||||||
|
<div>管径规格:${pipeSize}</div>
|
||||||
|
<div>坐标:${coord}</div>
|
||||||
|
<div>类型:${layerName.toLowerCase().includes("雨水") ? "雨水管" : "污水管"}</div>
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
// 打开弹窗
|
||||||
|
infoWindow.openOnMap(e.lnglat);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. 鼠标悬浮管道高亮
|
||||||
|
geoJsonLayer.addEventListener("mouseover", function(e) {
|
||||||
|
// 保存原始样式
|
||||||
|
e.target.originalStyle = e.target.getStyle();
|
||||||
|
// 设置高亮样式
|
||||||
|
e.target.setStyle({
|
||||||
|
opacity: 1,
|
||||||
|
weight: e.target.originalStyle.weight + 1
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// 鼠标离开恢复原始样式
|
||||||
|
geoJsonLayer.addEventListener("mouseout", function(e) {
|
||||||
|
if (e.target.originalStyle) {
|
||||||
|
e.target.setStyle(e.target.originalStyle);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("✅ 管道图层渲染完成");
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error("❌ GeoJSON加载/渲染失败:", error);
|
||||||
|
alert(`加载失败:${error.message}\n请检查GeoJSON文件路径是否正确!`);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
2147
src/main/webapp/jsp/z_bigScreen/pipeline_data.geojson
Normal file
2147
src/main/webapp/jsp/z_bigScreen/pipeline_data.geojson
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user