好的, 我来为你创建一个使用 Bun、UnoCSS、HTMX 和 Elysia 的实时天气预报程序。这个程序将使用服务器端渲染 (SSR), 允许用户选择不同的城市, 并可以展示未来一天、三天或一周的天气预报。
首先, 让我们设置项目结构和安装必要的依赖:
- 创建项目并安装依赖:
mkdir weather-forecast
cd weather-forecast
bun init
bun add elysia @elysiajs/html @elysiajs/static unocss htmx.org- 创建以下文件结构:
weather-forecast/
├── src/
│ ├── index.ts
│ ├── weather.ts
│ └── views/
│ ├── layout.ts
│ └── forecast.ts
├── public/
│ └── styles.css
└── package.json
- 在
src/index.ts中设置主应用:
import { Elysia } from "elysia";
import { html } from "@elysiajs/html";
import { staticPlugin } from "@elysiajs/static";
import { layout } from "./views/layout";
import { forecast } from "./views/forecast";
import { getWeatherData } from "./weather";
const app = new Elysia()
.use(html())
.use(staticPlugin())
.get("/", ({ html }) => html(layout(forecast())))
.get("/forecast/:city/:days", async ({ params, html }) => {
const { city, days } = params;
const weatherData = await getWeatherData(city, parseInt(days));
return html(forecast(city, parseInt(days), weatherData));
})
.listen(3000);
console.log(`Server is running at http://localhost:${app.server?.port}`);- 在
src/weather.ts中创建一个模拟的天气数据获取函数:
export interface WeatherData {
date: string;
temperature: number;
description: string;
}
export async function getWeatherData(city: string, days: number): Promise<WeatherData[]> {
// 这里应该是实际的API调用,但我们用模拟数据代替
return Array.from({ length: days }, (_, i) => ({
date: new Date(Date.now() + i * 24 * 60 * 60 * 1000).toLocaleDateString(),
temperature: Math.round(Math.random() * 20 + 10),
description: ["Sunny", "Cloudy", "Rainy"][Math.floor(Math.random() * 3)]
}));
}- 在
src/views/layout.ts中创建布局组件:
export const layout = (content: string) => `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Weather Forecast</title>
<script src="https://unpkg.com/htmx.org@1.9.6"></script>
<link href="/public/styles.css" rel="stylesheet">
</head>
<body class="bg-gray-100 text-gray-800">
<div class="container mx-auto p-4">
<h1 class="text-3xl font-bold mb-4">Weather Forecast</h1>
${content}
</div>
</body>
</html>
`;- 在
src/views/forecast.ts中创建天气预报组件:
import { WeatherData } from "../weather";
export const forecast = (city: string = "", days: number = 1, weatherData: WeatherData[] = []) => `
<div>
<form hx-get="/forecast" hx-target="#forecast" class="mb-4">
<input type="text" name="city" value="${city}" placeholder="Enter city" class="p-2 border rounded">
<select name="days" class="p-2 border rounded">
<option value="1" ${days === 1 ? 'selected' : ''}>1 day</option>
<option value="3" ${days === 3 ? 'selected' : ''}>3 days</option>
<option value="7" ${days === 7 ? 'selected' : ''}>7 days</option>
</select>
<button type="submit" class="p-2 bg-blue-500 text-white rounded">Get Forecast</button>
</form>
<div id="forecast">
${city && weatherData.length > 0 ? `
<h2 class="text-2xl mb-2">Forecast for ${city}</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
${weatherData.map(day => `
<div class="bg-white p-4 rounded shadow">
<h3 class="font-bold">${day.date}</h3>
<p>Temperature: ${day.temperature}°C</p>
<p>Description: ${day.description}</p>
</div>
`).join('')}
</div>
` : ''}
</div>
</div>
`;- 在
public/styles.css中添加 UnoCSS 样式:
@import 'https://cdn.jsdelivr.net/npm/@unocss/reset/tailwind.min.css';
@unocss all;- 更新
package.json中的 scripts:
{
"scripts": {
"dev": "bun run --watch src/index.ts"
}
}现在, 你可以运行 bun run dev 来启动服务器。访问 http://localhost:3000 就能看到天气预报应用了。
这个应用使用了:
- Elysia 作为 web 框架
- HTMX 进行无刷新的页面更新
- UnoCSS 进行样式设置
- 服务器端渲染 (SSR) 生成初始 HTML
- 允许用户选择不同的城市和预报天数
注意, 这个例子使用了模拟的天气数据。在实际应用中, 你需要替换 getWeatherData 函数, 使用真实的天气 API 来获取数据。