ahyd_DIB/bayonet_owner_tree.html
ylj20011123 39c03aba5a update
2026-01-19 11:01:17 +08:00

623 lines
25 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>卡口车主树形数据查询</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Microsoft YaHei', Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1400px;
margin: 0 auto;
background: rgba(255, 255, 255, 0.95);
border-radius: 20px;
padding: 30px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
}
h1 {
color: #333;
text-align: center;
margin-bottom: 30px;
font-size: 28px;
font-weight: 600;
}
.input-section {
background: #f8f9fa;
border-radius: 12px;
padding: 25px;
margin-bottom: 20px;
}
.input-group {
margin-bottom: 20px;
}
.input-group:last-child {
margin-bottom: 0;
}
.input-label {
display: block;
font-size: 14px;
font-weight: 600;
color: #333;
margin-bottom: 8px;
}
.input-hint {
font-size: 12px;
color: #666;
margin-top: 5px;
}
.input-field {
width: 100%;
padding: 12px 15px;
border: 2px solid #e0e0e0;
border-radius: 8px;
font-size: 14px;
transition: all 0.3s ease;
font-family: 'Microsoft YaHei', Arial, sans-serif;
}
.input-field:focus {
outline: none;
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
.query-btn {
width: 100%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 14px 20px;
border-radius: 8px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
}
.query-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
}
.query-btn:active {
transform: translateY(0);
}
.query-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
}
.info-section {
background: #e3f2fd;
border-radius: 8px;
padding: 15px;
margin-bottom: 20px;
border-left: 4px solid #2196f3;
}
.info-item {
font-size: 14px;
color: #555;
margin-bottom: 5px;
}
.info-item:last-child {
margin-bottom: 0;
}
.info-item strong {
color: #333;
margin-right: 10px;
}
.data-section {
margin-top: 30px;
}
.data-title {
font-size: 20px;
color: #667eea;
margin-bottom: 15px;
font-weight: 600;
border-left: 4px solid #667eea;
padding-left: 12px;
display: flex;
justify-content: space-between;
align-items: center;
}
.copy-btn {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 10px 20px;
border-radius: 8px;
font-size: 14px;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
}
.copy-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
}
.copy-btn:active {
transform: translateY(0);
}
.copy-btn.copied {
background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
}
.data-content {
background: #f8f9fa;
border-radius: 8px;
padding: 15px;
overflow-x: auto;
max-height: 600px;
overflow-y: auto;
}
pre {
margin: 0;
font-size: 13px;
line-height: 1.6;
color: #333;
}
.loading {
text-align: center;
padding: 40px;
font-size: 18px;
color: #667eea;
}
.error {
background: #fee;
color: #c33;
padding: 15px;
border-radius: 8px;
margin-bottom: 20px;
border-left: 4px solid #c33;
}
.success {
background: #e8f5e9;
color: #2e7d32;
padding: 15px;
border-radius: 8px;
margin-bottom: 20px;
border-left: 4px solid #4caf50;
}
.spinner {
border: 4px solid #f3f3f3;
border-top: 4px solid #667eea;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
margin: 20px auto;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.progress-info {
text-align: center;
color: #667eea;
font-size: 14px;
margin-top: 10px;
}
</style>
</head>
<body>
<div class="container">
<h1>卡口车主树形数据查询</h1>
<!-- 输入区域 -->
<div class="input-section">
<div class="input-group">
<label class="input-label">服务区 ID</label>
<input type="text" id="serverpartIdInput" class="input-field"
placeholder="请输入服务区ID,多个服务区用英文逗号隔开,例如: 1001,1002,1003"
value="362,363,364,365,366,367,368,369,370,371,372,373,376,377,378,379,380,381,382,383,384,385,416,417,418,419,420,421,422,424,426,428,429,430,431,432,433,434,435,436,439,440,442,443,444,445,446,448,450,451,453,456,460,462,463,464,465,466,468,470,471,473,474,475,476,477,478,479,480,489,490,492,494,495,496,498,499,500,501,502,503,504,505,507,508,509,510,511,513,514,515,516,517,518,519,520,521,522,524,525,592,594,600,606,646,652,656,658,659,694,706,707,708,710,714,716,756,803,805,811,819,941,943,951,955,963,967">
<div class="input-hint">提示: 留空则查询所有服务区,多个ID用逗号分隔</div>
</div>
<div class="input-group">
<label class="input-label">统计月份</label>
<input type="text" id="statisticsDateInput" class="input-field" placeholder="格式: 202512" readonly>
<div class="input-hint">从 URL 参数 Statistics_Date 获取,默认为 202512,同时用于开始和结束月份</div>
</div>
<button id="queryBtn" class="query-btn">🔍 查询数据</button>
</div>
<!-- 查询信息 -->
<div id="infoDiv" style="display: none;"></div>
<!-- 加载中 -->
<div id="loadingDiv" style="display: none;" class="loading">
<div class="spinner"></div>
<p id="loadingText">正在加载数据...</p>
<div id="progressInfo" class="progress-info"></div>
</div>
<!-- 错误提示 -->
<div id="errorDiv" style="display: none;"></div>
<!-- 结果展示 -->
<div id="resultDiv" style="display: none;">
<div class="data-section">
<div class="data-title">
查询结果 (Result_Data)
<button id="copyBtn" class="copy-btn">📋 复制数据</button>
</div>
<div class="data-content">
<pre id="resultData"></pre>
</div>
</div>
</div>
</div>
<script>
// 服务区 ID 到名称的映射表
const serverpartMap = {
"362": "香铺服务区", "363": "公岭服务区", "364": "王河服务区", "365": "潜山服务区",
"366": "天柱山服务区", "367": "岳西服务区", "368": "白帽服务区", "369": "太湖服务区",
"370": "宿松服务区", "371": "雷埠服务区", "372": "大龙山服务区", "373": "望江服务区",
"376": "河口服务区", "377": "西桥服务区", "378": "罗集服务区", "379": "徐集服务区",
"380": "梅山服务区", "381": "天堂寨服务区", "382": "长岭关服务区", "383": "霍山服务区",
"384": "茶庵服务区", "385": "芍陂服务区", "416": "新桥服务区", "417": "肥东服务区",
"418": "丰乐服务区", "419": "龙门寺服务区", "420": "巢湖服务区", "421": "陈埠服务区",
"422": "文集服务区", "424": "安徽驿达", "426": "临泉服务区", "428": "阜南服务区",
"429": "红星服务区", "430": "颍上服务区", "431": "焦岗湖服务区", "432": "八公山服务区",
"433": "官塘服务区", "434": "凤台服务区", "435": "吴圩服务区", "436": "杜集服务区",
"439": "谯城服务区", "440": "辛集服务区", "442": "马集服务区", "443": "四方湖服务区",
"444": "吕望服务区", "445": "三角元服务区", "446": "长春服务区", "448": "伍明服务区",
"450": "蒙城服务区", "451": "石弓服务区", "453": "砀山服务区", "456": "王寨服务区",
"460": "符离服务区", "462": "宿州服务区", "463": "濉溪服务区", "464": "虞姬服务区",
"465": "石龙湖服务区", "466": "桥头服务区", "468": "冯庙服务区", "470": "蟠龙山服务区",
"471": "君王服务区", "473": "宁国服务区", "474": "金沙服务区", "475": "华阳服务区",
"476": "太平湖服务区", "477": "呈坎服务区", "478": "牯牛降服务区", "479": "齐云山服务区",
"480": "休宁服务区", "489": "沙溪服务区", "490": "周潭服务区", "492": "天门服务区",
"494": "马衙服务区", "495": "釜山服务区", "496": "牛头山服务区", "498": "大墅服务区",
"499": "顺安服务区", "500": "香泉服务区", "501": "滁州服务区", "502": "花园服务区",
"503": "清溪服务区", "504": "香隅服务区", "505": "太白服务区", "507": "九华山服务区",
"508": "太白岛服务区", "509": "升金湖服务区", "510": "皇甫山服务区", "511": "仓镇服务区",
"513": "月湾服务区", "514": "仓头服务区", "515": "南漪湖服务区", "516": "南陵服务区",
"517": "石涧服务区", "518": "寒亭服务区", "519": "郎溪服务区", "520": "福山服务区",
"521": "新芜服务区", "522": "千军服务区", "524": "广德服务区", "525": "新竹服务区",
"592": "皇藏峪服务区", "594": "全椒服务区", "600": "石沛服务区", "606": "禹会服务区",
"646": "殷家汇服务区", "652": "南陵家发服务区", "656": "白荡湖服务区", "658": "旌德服务区",
"659": "泾县服务区", "694": "浮山服务区", "706": "天长西服务区", "707": "来安北服务区",
"708": "石台牯牛降服务区", "710": "深渡服务区", "714": "万佛湖服务区", "716": "小井庄服务区",
"756": "柏溪服务区", "803": "温泉服务区", "805": "青草服务区", "811": "庐江东服务区",
"819": "公桥服务区", "941": "八里河服务区", "943": "迎河服务区", "951": "临泉西服务区",
"955": "涡阳服务区", "963": "月亮湾服务区", "967": "洪林服务区"
};
// 从 URL 参数获取值
function getUrlParameter(name) {
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get(name);
}
// 树节点包装处理函数
function wrapTreeNode(data) {
if (!data || !Array.isArray(data)) {
return [];
}
const wrapData = data.map((item) => {
const node = { ...item.node };
if (item.children && item.children.length > 0) {
node.children = wrapTreeNode(item.children);
}
return node;
});
return wrapData;
}
// 处理 children 数据,当超过5条时创建汇总对象
function processChildrenData(dataObj) {
if (!dataObj || !dataObj.children || dataObj.children.length <= 5) {
return dataObj; // 不需要处理
}
const topFive = dataObj.children.slice(0, 5); // 前5条
const others = dataObj.children.slice(5); // 第6条及以后
// 创建汇总对象
const summaryObj = {
Index: 999,
ProvinceName: "其他",
// 从前5条的第一条复制服务区相关字段
ServerPartLevel: topFive[0].ServerPartLevel,
SPRegionTypeIndex: topFive[0].SPRegionTypeIndex,
SPRegionTypeId: topFive[0].SPRegionTypeId,
SPRegionTypeNAME: topFive[0].SPRegionTypeNAME,
ServerPartId: topFive[0].ServerPartId,
ServerPartName: topFive[0].ServerPartName,
// 其他字段初始化为 null
CityName: null,
SectionFlow: null,
EntryRate: null,
// 累加字段初始化为 0
EastLightDutyCount: 0,
EastMidSizeCount: 0,
EastLargeCount: 0,
WestLightDutyCount: 0,
WestMidSizeCount: 0,
WestLargeCount: 0,
LightDutyTotalCount: 0,
MidSizeTotalCount: 0,
LargeTotalCount: 0,
TotalCount: 0
};
// 累加第6条及以后的数据
others.forEach(item => {
summaryObj.EastLightDutyCount += (item.EastLightDutyCount || 0);
summaryObj.EastMidSizeCount += (item.EastMidSizeCount || 0);
summaryObj.EastLargeCount += (item.EastLargeCount || 0);
summaryObj.WestLightDutyCount += (item.WestLightDutyCount || 0);
summaryObj.WestMidSizeCount += (item.WestMidSizeCount || 0);
summaryObj.WestLargeCount += (item.WestLargeCount || 0);
summaryObj.LightDutyTotalCount += (item.LightDutyTotalCount || 0);
summaryObj.MidSizeTotalCount += (item.MidSizeTotalCount || 0);
summaryObj.LargeTotalCount += (item.LargeTotalCount || 0);
summaryObj.TotalCount += (item.TotalCount || 0);
});
// 重组 children: 前5条 + 汇总对象
dataObj.children = [...topFive, summaryObj];
return dataObj;
}
// 模拟 request.$webGet 方法
const request = {
$webGet: async function (url, params) {
const baseUrl = 'https://api.eshangtech.com/CommercialApi/';
const queryString = new URLSearchParams(params).toString();
const fullUrl = `${baseUrl}${url}?${queryString}`;
const response = await fetch(fullUrl, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
}
};
// 初始化页面
function initPage() {
const statisticsDate = getUrlParameter('Statistics_Date') || '202512';
document.getElementById('statisticsDateInput').value = statisticsDate;
}
// 查询数据
async function queryData() {
try {
// 隐藏之前的结果和错误
document.getElementById('resultDiv').style.display = 'none';
document.getElementById('errorDiv').style.display = 'none';
document.getElementById('infoDiv').style.display = 'none';
// 显示加载状态
document.getElementById('loadingDiv').style.display = 'block';
document.getElementById('loadingText').textContent = '正在加载数据...';
document.getElementById('progressInfo').textContent = '';
document.getElementById('queryBtn').disabled = true;
// 获取输入值
const serverpartIdInput = document.getElementById('serverpartIdInput').value.trim();
const statisticsDate = document.getElementById('statisticsDateInput').value.trim();
// 处理服务区 ID
let serverpartIds = [];
if (serverpartIdInput) {
serverpartIds = serverpartIdInput.split(',').map(id => id.trim()).filter(id => id);
}
// 构建基础请求参数
const baseReq = {
dataType: 1,
statisticsStartMonth: statisticsDate,
statisticsEndMonth: statisticsDate,
rankNum: 5,
isSync: false
};
let allResultData = [];
if (serverpartIds.length === 0) {
// 没有输入服务区 ID,查询所有
document.getElementById('loadingText').textContent = '正在查询所有服务区数据...';
const req = { ...baseReq, serverPartId: '' };
console.log('查询请求参数:', req);
const res = await request.$webGet('BigData/GetBayonetOwnerAHTreeList', req);
console.log('查询结果:', res);
if (res.Result_Code === 100 && res.Result_Data && res.Result_Data.List) {
// 提取 List 并使用 wrapTreeNode 处理
const wrappedData = wrapTreeNode(res.Result_Data.List);
console.log('wrapTreeNode 处理后:', wrappedData);
// 取第一项并处理 children
if (wrappedData && wrappedData.length > 0) {
const processedData = processChildrenData(wrappedData[0]);
console.log('processChildrenData 处理后:', processedData);
allResultData.push(processedData);
}
} else {
throw new Error(res.Result_Desc || '查询失败');
}
} else {
// 有多个服务区 ID,逐个查询
document.getElementById('loadingText').textContent = `正在查询 ${serverpartIds.length} 个服务区数据...`;
for (let i = 0; i < serverpartIds.length; i++) {
const serverpartId = serverpartIds[i];
const serverpartName = serverpartMap[serverpartId] || '未知服务区';
document.getElementById('progressInfo').textContent = `正在查询第 ${i + 1}/${serverpartIds.length} 个服务区 (ID: ${serverpartId} - ${serverpartName})`;
const req = { ...baseReq, serverPartId: serverpartId };
console.log(`查询服务区 ${serverpartId} 请求参数:`, req);
const res = await request.$webGet('BigData/GetBayonetOwnerAHTreeList', req);
console.log(`查询服务区 ${serverpartId} 结果:`, res);
if (res.Result_Code === 100 && res.Result_Data && res.Result_Data.List) {
// 提取 List 并使用 wrapTreeNode 处理
const wrappedData = wrapTreeNode(res.Result_Data.List);
console.log(`服务区 ${serverpartId} wrapTreeNode 处理后:`, wrappedData);
// 取第一项并处理 children,然后补充服务区信息
if (wrappedData && wrappedData.length > 0) {
const processedData = processChildrenData(wrappedData[0]);
console.log(`服务区 ${serverpartId} processChildrenData 处理后:`, processedData);
const enrichedData = {
...processedData
};
allResultData.push(enrichedData);
}
} else {
console.warn(`服务区 ${serverpartId} 查询失败:`, res.Result_Desc);
}
}
}
// 显示查询信息
showInfo(serverpartIds, statisticsDate, statisticsDate, allResultData.length);
// 显示结果
displayData(allResultData);
} catch (error) {
console.error('查询失败:', error);
showError(error.message);
} finally {
document.getElementById('loadingDiv').style.display = 'none';
document.getElementById('queryBtn').disabled = false;
}
}
// 显示查询信息
function showInfo(serverpartIds, startMonth, endMonth, resultCount) {
const infoDiv = document.getElementById('infoDiv');
infoDiv.className = 'success';
let infoHtml = '<strong>✓ 查询成功</strong><br>';
infoHtml += `<div class="info-item"><strong>开始月份:</strong>${startMonth}</div>`;
infoHtml += `<div class="info-item"><strong>结束月份:</strong>${endMonth}</div>`;
infoHtml += `<div class="info-item"><strong>查询范围:</strong>${serverpartIds.length === 0 ? '所有服务区' : serverpartIds.length + ' 个服务区 (' + serverpartIds.join(', ') + ')'}</div>`;
infoHtml += `<div class="info-item"><strong>返回结果:</strong>${resultCount} 条数据</div>`;
infoDiv.innerHTML = infoHtml;
infoDiv.style.display = 'block';
}
// 显示数据
function displayData(resultData) {
document.getElementById('resultDiv').style.display = 'block';
const jsonString = JSON.stringify(resultData, null, 2);
document.getElementById('resultData').textContent = jsonString;
// 添加复制按钮事件(移除旧的事件监听器)
const copyBtn = document.getElementById('copyBtn');
const newCopyBtn = copyBtn.cloneNode(true);
copyBtn.parentNode.replaceChild(newCopyBtn, copyBtn);
newCopyBtn.addEventListener('click', function () {
navigator.clipboard.writeText(jsonString).then(() => {
const originalText = newCopyBtn.textContent;
newCopyBtn.textContent = '✓ 已复制!';
newCopyBtn.classList.add('copied');
setTimeout(() => {
newCopyBtn.textContent = originalText;
newCopyBtn.classList.remove('copied');
}, 2000);
}).catch(err => {
console.error('复制失败:', err);
alert('复制失败,请手动复制');
});
});
}
// 显示错误
function showError(message) {
const errorDiv = document.getElementById('errorDiv');
errorDiv.className = 'error';
errorDiv.innerHTML = `<strong>错误:</strong> ${message}`;
errorDiv.style.display = 'block';
}
// 绑定查询按钮事件
document.getElementById('queryBtn').addEventListener('click', queryData);
// 输入框回车触发查询
document.getElementById('serverpartIdInput').addEventListener('keypress', function (e) {
if (e.key === 'Enter') {
queryData();
}
});
// 页面加载完成后初始化
window.addEventListener('DOMContentLoaded', initPage);
</script>
</body>
</html>