feat: introduce PolyWeather web map API and frontend with integrated weather data collection and analysis.
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
const fs = require('fs');
|
||||
|
||||
function replaceRegex(content, regex, replacement, label) {
|
||||
const next = content.replace(regex, replacement);
|
||||
if (next === content) {
|
||||
console.error('No match for', label);
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
const appJsPath = 'E:/web/PolyWeather/frontend/public/static/app.js';
|
||||
let app = fs.readFileSync(appJsPath, 'utf8');
|
||||
|
||||
app = replaceRegex(app, /function updateCityListInfo\(cityData\) \{[\s\S]*?\n\}/, `function updateCityListInfo(cityData) {
|
||||
const cityName = cityData.name;
|
||||
const cityId = cityName.replace(/\\s/g, "-");
|
||||
const temp = cityData.current?.temp;
|
||||
|
||||
const tempEl = document.getElementById(\`temp-\${cityId}\`);
|
||||
if (tempEl && temp != null) {
|
||||
tempEl.textContent = \`\${temp}\${cityData.temp_symbol}\`;
|
||||
tempEl.classList.add("loaded");
|
||||
}
|
||||
|
||||
const timeEl = document.getElementById(\`time-\${cityId}\`);
|
||||
if (timeEl && cityData.local_time) {
|
||||
timeEl.textContent = \`🕐 \${cityData.local_time}\`;
|
||||
}
|
||||
|
||||
const maxEl = document.getElementById(\`max-\${cityId}\`);
|
||||
if (maxEl && cityData.current?.max_temp_time) {
|
||||
maxEl.textContent = \`峰值 @\${cityData.current.max_temp_time}\`;
|
||||
}
|
||||
}`,'updateCityListInfo');
|
||||
|
||||
app = app.replace(/alert\(`[^`]*cityName[^`]*`\);/, 'alert(`加载 ${cityName} 数据失败:${e.message}`);');
|
||||
|
||||
app = replaceRegex(app, /function renderPanel\(data\) \{[\s\S]*?\n\}/, `function renderPanel(data) {
|
||||
const panel = document.getElementById("panel");
|
||||
if (!panel) return;
|
||||
panel.classList.remove("hidden");
|
||||
requestAnimationFrame(() => panel.classList.add("visible"));
|
||||
|
||||
const panelCityName = document.getElementById("panelCityName");
|
||||
const panelLocalTime = document.getElementById("panelLocalTime");
|
||||
const badge = document.getElementById("panelRiskBadge");
|
||||
|
||||
if (panelCityName) {
|
||||
panelCityName.textContent = \`\${data.risk?.emoji || "🏙️"} \${data.display_name}\`;
|
||||
}
|
||||
if (panelLocalTime) {
|
||||
panelLocalTime.textContent = \`🕐 \${data.local_time || "--:--"} 当地时间\`;
|
||||
}
|
||||
if (badge) {
|
||||
badge.textContent = {
|
||||
high: "🔴 高危",
|
||||
medium: "🟡 中危",
|
||||
low: "🟢 低危",
|
||||
}[data.risk?.level] || "未知";
|
||||
badge.className = \`risk-badge \${data.risk?.level || "low"}\`;
|
||||
}
|
||||
|
||||
renderHero(data);
|
||||
renderChart(data);
|
||||
renderProbabilities(data);
|
||||
if (!selectedForecastDate) {
|
||||
selectedForecastDate = data.local_date;
|
||||
}
|
||||
renderModels(data);
|
||||
renderForecast(data);
|
||||
renderAI(data);
|
||||
renderRisk(data);
|
||||
}`,'renderPanel');
|
||||
|
||||
app = replaceRegex(app, /const METAR_WX_MAP = \{[\s\S]*?\n\};/, `const METAR_WX_MAP = {
|
||||
RA: { label: "降雨", icon: "🌧️" },
|
||||
"-RA": { label: "小雨", icon: "🌦️" },
|
||||
"+RA": { label: "强降雨", icon: "⛈️" },
|
||||
SN: { label: "降雪", icon: "❄️" },
|
||||
"-SN": { label: "小雪", icon: "🌨️" },
|
||||
"+SN": { label: "大雪", icon: "🌨️" },
|
||||
DZ: { label: "毛毛雨", icon: "🌦️" },
|
||||
FG: { label: "雾", icon: "🌫️" },
|
||||
BR: { label: "薄雾", icon: "🌫️" },
|
||||
HZ: { label: "霾", icon: "🌫️" },
|
||||
TS: { label: "雷暴", icon: "⛈️" },
|
||||
VCTS: { label: "附近雷暴", icon: "⛈️" },
|
||||
SQ: { label: "飑", icon: "💨" },
|
||||
GS: { label: "冰雹", icon: "🌨️" },
|
||||
};`, 'METAR_WX_MAP');
|
||||
|
||||
app = app.replace(/return \{ label: code, icon: .*? \};/, 'return { label: code, icon: "🌤️" };');
|
||||
|
||||
app = replaceRegex(app, /function renderHero\(data\) \{[\s\S]*?document.getElementById\("heroWeather"\)\.innerHTML = `/, `function renderHero(data) {
|
||||
const cur = data.current || {};
|
||||
const sym = data.temp_symbol || "°C";
|
||||
const displayTemp = cur.temp;
|
||||
|
||||
let weatherText = cur.cloud_desc || "未知";
|
||||
let weatherIcon =
|
||||
{
|
||||
多云: "☁️",
|
||||
阴天: "☁️",
|
||||
少云: "🌤️",
|
||||
散云: "☁️",
|
||||
晴: "☀️",
|
||||
晴朗: "☀️",
|
||||
}[cur.cloud_desc] || "🌤️";
|
||||
|
||||
if (cur.wx_desc) {
|
||||
const metarTranslation = translateMETAR(cur.wx_desc);
|
||||
if (metarTranslation) {
|
||||
weatherText = metarTranslation.label;
|
||||
weatherIcon = metarTranslation.icon;
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById("heroWeather").innerHTML = ``, 'renderHeroPrefix');
|
||||
|
||||
fs.writeFileSync(appJsPath, app, 'utf8');
|
||||
|
||||
const pagePath = 'E:/web/PolyWeather/frontend/app/page.tsx';
|
||||
let page = fs.readFileSync(pagePath, 'utf8');
|
||||
page = page.replace(/legacy-v13/g, 'legacy-v14');
|
||||
fs.writeFileSync(pagePath, page, 'utf8');
|
||||
|
||||
const htmlPath = 'E:/web/PolyWeather/frontend/public/legacy/index.html';
|
||||
let html = fs.readFileSync(htmlPath, 'utf8');
|
||||
html = html.replace(/legacy-v13/g, 'legacy-v14');
|
||||
fs.writeFileSync(htmlPath, html, 'utf8');
|
||||
Reference in New Issue
Block a user