224 lines
6.2 KiB
JavaScript
224 lines
6.2 KiB
JavaScript
// 房地产数据监控前端脚本
|
|
|
|
// 配置
|
|
const CONFIG = {
|
|
apiBase: '/api',
|
|
dateFormat: /^(\d{4})-(\d{2})-(\d{2})$/
|
|
};
|
|
|
|
// DOM元素
|
|
const elements = {
|
|
datePicker: document.getElementById('datePicker'),
|
|
loadBtn: document.getElementById('loadBtn'),
|
|
todayBtn: document.getElementById('todayBtn'),
|
|
loading: document.getElementById('loading'),
|
|
error: document.getElementById('error'),
|
|
content: document.getElementById('content'),
|
|
dataDate: document.getElementById('dataDate'),
|
|
lastUpdate: document.getElementById('lastUpdate')
|
|
};
|
|
|
|
// 表格映射
|
|
const tableMap = {
|
|
'ksqf': 'kespTable',
|
|
'ysxk': 'ysxkTable',
|
|
'qfrg': 'qfrgTable',
|
|
'qfqy': 'qfqyTable',
|
|
'wyxf': 'wyqxTable',
|
|
'xfxm': 'xfxmTable',
|
|
'xfrg': 'xfrgTable',
|
|
'xfqy': 'xfqyTable',
|
|
'clf_month': 'clfyqyTable',
|
|
'clf_day': 'clfrqyTable'
|
|
};
|
|
|
|
// 初始化
|
|
function init() {
|
|
// 设置日期选择器默认值为今天
|
|
const today = new Date().toISOString().split('T')[0];
|
|
elements.datePicker.value = today;
|
|
|
|
// 绑定事件
|
|
elements.loadBtn.addEventListener('click', () => loadData(elements.datePicker.value));
|
|
elements.todayBtn.addEventListener('click', () => {
|
|
elements.datePicker.value = today;
|
|
loadData(today);
|
|
});
|
|
|
|
// 加载今天的数据
|
|
loadData(today);
|
|
|
|
// 更新最后更新时间
|
|
elements.lastUpdate.textContent = new Date().toLocaleString('zh-CN');
|
|
}
|
|
|
|
// 加载数据
|
|
async function loadData(date) {
|
|
if (!date) {
|
|
showError('请选择日期');
|
|
return;
|
|
}
|
|
|
|
showLoading();
|
|
|
|
try {
|
|
const response = await fetch(`${CONFIG.apiBase}/data/${date}`);
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`未找到 ${date} 的数据`);
|
|
}
|
|
|
|
const data = await response.json();
|
|
|
|
if (data.error) {
|
|
throw new Error(data.error);
|
|
}
|
|
|
|
displayData(data);
|
|
showContent();
|
|
} catch (err) {
|
|
showError(`加载失败: ${err.message}`);
|
|
}
|
|
}
|
|
|
|
// 显示数据
|
|
function displayData(data) {
|
|
elements.dataDate.textContent = data.date;
|
|
|
|
// 商品房数据统计
|
|
const spfData = data.data.spfsjtj;
|
|
for (const [key, value] of Object.entries(spfData)) {
|
|
const tableId = tableMap[key];
|
|
if (tableId) {
|
|
renderSimpleTable(document.getElementById(tableId), value, rootDefined.spfsjtj.childMap[key].childMap);
|
|
}
|
|
}
|
|
|
|
// 存量房月统计
|
|
const clfData = data.data.clfwsqytj;
|
|
for (const [key, value] of Object.entries(clfData)) {
|
|
const tableId = tableMap[key];
|
|
if (tableId) {
|
|
renderSimpleTable(document.getElementById(tableId), value, rootDefined.clfwsqytj.childMap[key].childMap);
|
|
}
|
|
}
|
|
|
|
// 经纪机构表格
|
|
const jjjgData = data.data.clfwdtj.broker;
|
|
renderBrokerTable(document.getElementById('jjjgTable'), jjjgData, rootDefined.clfwdtj.childMap.broker.childMap);
|
|
|
|
// 按所在区县表格
|
|
const districtData = data.data.clfwdtj.district;
|
|
renderBrokerTable(document.getElementById('szqxTable'), districtData, rootDefined.clfwdtj.childMap.district.childMap);
|
|
|
|
// 按建筑面积
|
|
const areaData = data.data.clfwdtj.area;
|
|
renderBrokerTable(document.getElementById('jzmjTable'), areaData, rootDefined.clfwdtj.childMap.area.childMap);
|
|
|
|
// 加载截图
|
|
loadScreenshot(data.date);
|
|
}
|
|
|
|
// 加载截图
|
|
function loadScreenshot(date) {
|
|
const container = document.getElementById('screenshotContainer');
|
|
const img = new Image();
|
|
img.src = `/pic/${date}.png`;
|
|
img.alt = '页面截图';
|
|
img.className = 'screenshot-img';
|
|
|
|
img.onload = function() {
|
|
container.innerHTML = '';
|
|
container.appendChild(img);
|
|
};
|
|
|
|
img.onerror = function() {
|
|
container.innerHTML = '<p>暂无截图</p>';
|
|
};
|
|
}
|
|
|
|
// 渲染简单表格(键值对)
|
|
function renderSimpleTable(table, data, fieldMap) {
|
|
table.innerHTML = '';
|
|
|
|
if (!data || Object.keys(data).length === 0) {
|
|
table.innerHTML = '<tr><td colspan="2">暂无数据</td></tr>';
|
|
return;
|
|
}
|
|
|
|
for (const item of Object.values(fieldMap)) {
|
|
const row = document.createElement('tr');
|
|
row.innerHTML = `
|
|
<td>${item.label}</td>
|
|
<td>${data[item.key]}</td>
|
|
`;
|
|
table.appendChild(row);
|
|
}
|
|
}
|
|
|
|
// 渲染经纪机构表格
|
|
function renderBrokerTable(table, data, fieldMap) {
|
|
table.innerHTML = '';
|
|
|
|
if (!data || data.length === 0) {
|
|
table.innerHTML = '<tr><td colspan="4">暂无数据</td></tr>';
|
|
return;
|
|
}
|
|
|
|
// 表头
|
|
const thead = document.createElement('thead');
|
|
thead.innerHTML = `
|
|
<tr>${Object.values(fieldMap).map(item => `<th>${item.label}</th>`).join('')}</tr>
|
|
`;
|
|
table.appendChild(thead);
|
|
|
|
// 表体
|
|
const tbody = document.createElement('tbody');
|
|
data.forEach(item => {
|
|
const row = document.createElement('tr');
|
|
row.innerHTML = Object.values(fieldMap).map(field => `<td>${item[field.key]}</td>`).join('');
|
|
tbody.appendChild(row);
|
|
});
|
|
table.appendChild(tbody);
|
|
}
|
|
|
|
// 格式化数字
|
|
function formatNumber(num) {
|
|
if (num === null || num === undefined) return '-';
|
|
const n = parseFloat(num);
|
|
if (isNaN(n)) return num;
|
|
|
|
// 如果是整数,添加千分位
|
|
if (Number.isInteger(n)) {
|
|
return n.toLocaleString('zh-CN');
|
|
}
|
|
|
|
// 保留2位小数
|
|
return n.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
}
|
|
|
|
// 显示加载状态
|
|
function showLoading() {
|
|
elements.loading.classList.remove('hidden');
|
|
elements.error.classList.add('hidden');
|
|
elements.content.classList.add('hidden');
|
|
}
|
|
|
|
// 显示错误
|
|
function showError(message) {
|
|
elements.loading.classList.add('hidden');
|
|
elements.error.textContent = message;
|
|
elements.error.classList.remove('hidden');
|
|
elements.content.classList.add('hidden');
|
|
}
|
|
|
|
// 显示内容
|
|
function showContent() {
|
|
elements.loading.classList.add('hidden');
|
|
elements.error.classList.add('hidden');
|
|
elements.content.classList.remove('hidden');
|
|
}
|
|
|
|
// 启动
|
|
document.addEventListener('DOMContentLoaded', init);
|