feat: implement multilingual SEO support and enhance map UI with data synchronization updates
This commit is contained in:
+28
-61
@@ -78,70 +78,37 @@ async function scrapeLake(lakeId: string, oid: string, internalId: string) {
|
||||
});
|
||||
|
||||
const records: DataRecord[] = [];
|
||||
let dataTable = null;
|
||||
$('table').each((i, tbl) => {
|
||||
if ($(tbl).text().includes('Datum') && $(tbl).text().includes('Odtok')) {
|
||||
dataTable = $(tbl);
|
||||
}
|
||||
});
|
||||
|
||||
const parseTable = (htmlContent: string) => {
|
||||
const _$ = cheerio.load(htmlContent);
|
||||
let dataTable = null;
|
||||
_$('table').each((i, tbl) => {
|
||||
if (_$(tbl).text().includes('Datum') && _$(tbl).text().includes('Odtok')) {
|
||||
dataTable = _$(tbl);
|
||||
if (dataTable) {
|
||||
dataTable.find('tr').each((i, row) => {
|
||||
if (i === 0) return; // skip header
|
||||
const cols = $(row).find('td');
|
||||
if (cols.length >= 3) {
|
||||
const rawDate = $(cols[0]).text().trim();
|
||||
const levelStr = $(cols[1]).text().trim().replace(',', '.');
|
||||
let flowStr = $(cols[2]).text().trim().replace(',', '.');
|
||||
if (flowStr === '' && cols.length >= 4) {
|
||||
flowStr = $(cols[3]).text().trim().replace(',', '.');
|
||||
}
|
||||
|
||||
const parsedDateStr = parseDateString(rawDate);
|
||||
if (parsedDateStr) {
|
||||
records.push({
|
||||
timestamp: parsedDateStr,
|
||||
level: parseFloat(levelStr) || 0,
|
||||
flow: parseFloat(flowStr) || 0,
|
||||
inflow: 0,
|
||||
volume: 0
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (dataTable) {
|
||||
dataTable.find('tr').each((i, row) => {
|
||||
if (i === 0) return; // skip header
|
||||
const cols = _$(row).find('td');
|
||||
if (cols.length >= 3) {
|
||||
const rawDate = _$(cols[0]).text().trim();
|
||||
const levelStr = _$(cols[1]).text().trim().replace(',', '.');
|
||||
let flowStr = _$(cols[2]).text().trim().replace(',', '.');
|
||||
if (flowStr === '' && cols.length >= 4) {
|
||||
flowStr = _$(cols[3]).text().trim().replace(',', '.');
|
||||
}
|
||||
|
||||
const parsedDateStr = parseDateString(rawDate);
|
||||
if (parsedDateStr) {
|
||||
records.push({
|
||||
timestamp: parsedDateStr,
|
||||
level: parseFloat(levelStr) || 0,
|
||||
flow: parseFloat(flowStr) || 0,
|
||||
inflow: 0,
|
||||
volume: 0
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 1. Zpracování týdenních dat (GET)
|
||||
parseTable(response.data);
|
||||
|
||||
// 2. Získání a zpracování měsíčních dat (POST)
|
||||
try {
|
||||
const viewstate = $('#__VIEWSTATE').val();
|
||||
const viewstategenerator = $('#__VIEWSTATEGENERATOR').val();
|
||||
const eventvalidation = $('#__EVENTVALIDATION').val();
|
||||
|
||||
if (viewstate && viewstategenerator && eventvalidation) {
|
||||
const postData = new URLSearchParams();
|
||||
postData.append('__EVENTTARGET', 'ctl00$ObsahCPH$PrechodNaBilancniData');
|
||||
postData.append('__EVENTARGUMENT', '');
|
||||
postData.append('__VIEWSTATE', viewstate as string);
|
||||
postData.append('__VIEWSTATEGENERATOR', viewstategenerator as string);
|
||||
postData.append('__EVENTVALIDATION', eventvalidation as string);
|
||||
|
||||
const postRes = await axios.post(URL, postData.toString(), {
|
||||
httpsAgent: agent,
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
timeout: 10000
|
||||
});
|
||||
|
||||
parseTable(postRes.data);
|
||||
}
|
||||
} catch (err: any) {
|
||||
console.warn(`Failed to fetch monthly data for ${internalId}:`, err.message);
|
||||
}
|
||||
|
||||
if (records.length > 0) {
|
||||
|
||||
Reference in New Issue
Block a user